On Wed, Jun 24, 2015 at 2:07 PM, Albert C. Baker III <alb...@voltage.com> wrote: > I am using the Java class org.apache.hadoop.security. > authentication.server.AuthenticationFilter from Apache > Hadoop 2.5.0 as a filter in front of a Tomcat 6 Servlet we > wish to add Kerberos authentication to. > > I am attempting to write some test cases against this filter > so that we have a better understanding of how it > works and what it does. > > In order for the filter to authenticate a user, it is reading the > 'Authorization' header of the HTTP request, > expecting the value to contain 'Negotiate <base64 encoded data>' > > My understanding of how Kerberos works leads me to believe that I > should be able to write code while creating my > HTTP request that looks something like this: > > // normally the server principal keytab is not available from the > client side, > // but for the purpose of making test cases I see no problem with > sharing the keytab > // between the client side and the server side > javax.security.auth.kerberos.Keytab kt = KeyTab.getInstance("keytab"); > KerberosKey keys[] = kt.getKeys("HTTP/voltage-pp- > 0000.albert....@alberts.int");
Hi Albert, This *should* be possible but unfortunately it's not. Last I checked (which was probably several years ago), you actually cannot initiate Kerberos authentication from just a raw Kerberos key using the builtin Java API in a platform independent way. Specifically, on Windows you MUST use the Kerberos LoginModule to "login" first. Otherwise, you will get an error when you try to use the security context. The above code would work fine on non-Windows platforms like Linux but on Windows, the builtin Java Kerberos library uses the Windows credential cache and SSPI (the security API for Windows) so that the Java program will use the system credential cache (instead of a ccache file), identity of the user and existing system Kerberos configuration. In theory it should still be possible to initiate auth using only a Kerberos key like in your code but again, last I checked, it unfortunately does not work and I have no explanation as to why other than to recall that the builtin Java Kerberos library has been a point of criticism and outright failure since forever (although it has gotten better over the years). Note that the reason the Windows SSPI is used by Java is largely because there is otherwise no way to insert credentials into the Windows credential cache. It actually used to be possible but at some point early on MS decided this was probably not a good idea and so now Java and MIT or Heimdal or whoever cannot insert creds into the Windows credential cache. They have to just use the Windows Kerberos SSPI. > SomeTokenType token = new SomeTokenType(); > <code to set token parameters> > > // my understanding of Kerberos is that the only cyphertext key > // needed on this token > // is one of the server principal's keys from the Keytab file > // (which does contain ~5 > // keys of different sizes and types, I've checked) > EncryptedTokenType etoken = <encrypt token with a key from keys> > byte[] array = etoken.getBytes(); First, note that the "token" in the Authorization / WWW-Authenticate headers in HTTP are not quite the same as the "token" as defined in the Kerberos protocol documentation. Technically, the HTTP "token" is the Base64 encoded product of the InitializeSecurityContext function of the Microsoft Windows SSPI of which there are several but could be Kerberos or NTLM but in practice almost always SPNEGO which is a little binary wrapper used to NEGOtiate Keberos or NTLMSSP where NTLMSSP is a little binary wrapper around NTLM. Lost yet? Anyway, with respect to Windows HTTP clients (including Firefox and Chrome running on Windows which just tap into the Windows SSPI), the HTTP "token" is almost certainly an SPNEGO token. However, if you're just trying to initiate authentication (meaning you're the client), you can *probably* skip SPNEGO and feed the server a raw Kerberos token. At least Windows servers like IIS should detect this and handle it correctly. And Apache's mod_auth_kerb would almost certainly handle it correctly as well. Regarding the keytab, yes, it contains the target principal keys although technically you only need the one with the principal name that matches the target you're trying to authenticate with (HTTP/www.example.com). > httprequest.addHeader("Authorization","Negotiate " + new > Base64(0).encode(array)); > > So, questions here: > 1) What is the Java Class that embodies the Kerberos Auth Token sent > in "Authorization Negotiate"? Again I am not familiar with your "token" code but fortunately, even though the Authorization: Negotiate ... token is an Internet Explorer-ism, it's SPNEGO payload is largely compatible with the Kerberos token and more generally the GSSAPI token where GSSAPI is the RFC definition of this type of authentication which is meaningful because JGSS is the Java implementation of this and this is a run-on sentence. Meaning GSSAPI's GSS_Init_sec_context() is largely compatible with Windows' InitializeSecurityContext(). So with respect to actually coding a Java HTTP client to do Kerberos, something would ultimately need to call GSSManager.createContext with the Kerberos OID and then GSSContext.initSecContext and then the result of looping over that consumes and emits a "token" (which *should* then be wrapped in the SPNEGO business) and Base64 encoded / decoded. Maybe the "Hadoop" library is doing that for you. I'm not familiar with it. Personally I would be very skeptical of libraries that do this type of stuff. HTTP authentication is actually a lot harder than it looks because HTTP is stateless and so technically trying to do authentication (which is inherently stateful) over a stateless protocol is something of an oxymoron. So test your code carefully using all of the possible environmental parameters like different servers or whatever. > 2) What fields of that auth token have to be set to what values? > 3) What is the encryption algorithm used to encrypt the auth token > against the keytab key? > 4) What is the best keytab key to use? > 5) What is the mechanism for byte-serializing the auth token, once > encrypted? As described above, fortunately you probably don't have to worry about the actual content of the token as it is largely handled by GSSAPI / JGSS. Mike -- Michael B Allen Java Active Directory Integration http://www.ioplex.com/ ________________________________________________ Kerberos mailing list Kerberos@mit.edu https://mailman.mit.edu/mailman/listinfo/kerberos