This discussion is archived
0 Replies Latest reply: Oct 19, 2012 7:46 AM by 969563 RSS

Kerberos RMI - Spring Remoting

969563 Newbie
Currently Being Moderated
For some time I have been analyzing the possibility of using Kerberos in RMI apps.
I know that this challenging issue but I decided to use interceptors withing Spring remoting framework
which contains extra transport layer.

I was inspired by the following example (muthual authentication turned off)
http://thejavamonkey.blogspot.com/2008/04/clientserver-hello-world-in-kerberos.html , where ticket is saved on disk and there is no 'while'for GSSContext accept. If there is no while there is no need for using socket factories?

In my solution, the Kerberos ticket is send using apropriate ContextInvocationFactories.
The client is connecting to the KDC, TGT is generated and service ticket is calculated for validation
on the server side.

On the server side I'm using RemoteInvocationExecutor which plays role of 'intercepting filter' where the genenerated ticket is obtained. But during the processing I get some errors.

First of all the server is multithreaded so I'm wondering if the GSSContext can be shared between many
customers or each customer should have assigned the separate instance?

1. In my first approach the GSS context is generated on each invocation of the intercepting filter.
This is problematic because as I assume the operation is not performed within main server thread
in which TGT was obtained and during context creation the error is as foolows:
GSSException: No valid credentials provided (Mechanism level: Failed to find any Kerberos credentails)
        at sun.security.jgss.krb5.Krb5AcceptCredential.getInstance(Krb5AcceptCredential.java:89)
        at sun.security.jgss.krb5.Krb5MechFactory.getCredentialElement(Krb5MechFactory.java:126)
        at sun.security.jgss.GSSManagerImpl.getCredentialElement(GSSManagerImpl.java:192)
        at sun.security.jgss.GSSCredentialImpl.add(GSSCredentialImpl.java:406)
        at sun.security.jgss.GSSCredentialImpl.<init>(GSSCredentialImpl.java:60)
        at sun.security.jgss.GSSManagerImpl.createCredential(GSSManagerImpl.java:153)
The code:
return Subject.doAsPrivileged( serverSubject, new PrivilegedAction<String>() {
               public String run() {
                    try {
                         Oid krb5Oid = new Oid( "1.2.840.113554.1.2.2");
                         // Identify the server that communications are being made to.
                         GSSManager manager = GSSManager.getInstance();
                         
                         // Modified
                         GSSName serverName = manager.createName( 
                                   "rmi-services/gmaccountingsystem/ubuntu-kerberos-srv.atsi", 
                                   GSSName.NT_HOSTBASED_SERVICE);
                         GSSCredential serverCreds = manager.createCredential(serverName,
                                   GSSCredential.DEFAULT_LIFETIME, krb5Oid,
                                   GSSCredential.ACCEPT_ONLY);
                         GSSContext context = manager.createContext( serverCreds );          
                         
                         context.acceptSecContext( serviceTicket, 0, serviceTicket.length);
                         return context.getSrcName().toString();
                    }
                    catch ( GSSException e) {
                         e.printStackTrace();
                         return null;
                    }
               }
          }, acc);
2. In the second approach the GSSContext is generated during server startup and saved in the 'ApplicationContext'.
AccessControlContext is also saved in the 'ApplicationContext'.

During invocation of the filter ticket it is obtained from the method context and the checking is performed:
     // Completes the security context initialisation and returns the client name.
     public static String acceptSecurityContext(Subject serverSubject, final byte[] serviceTicket, 
               final AccessControlContext acc, final GSSContext context)
          throws GSSException { 
          
          return Subject.doAsPrivileged( serverSubject, new PrivilegedAction<String>() {
               public String run() {
                    try {
                         context.acceptSecContext( serviceTicket, 0, serviceTicket.length);
                         return context.getSrcName().toString();
                    }
                    catch ( GSSException e) {
                         e.printStackTrace();
                         return null;
                    }
               }
          }, acc);
     }
but the validation is not successful:
Caused by: java.lang.IllegalStateException: This key is no longer valid
    at javax.security.auth.kerberos.KerberosKey.getEncoded(KerberosKey.java:207)
    at sun.security.jgss.krb5.Krb5Util$ServiceCreds.getEKeys(Krb5Util.java:304)
    at sun.security.jgss.krb5.Krb5AcceptCredential.getKrb5EncryptionKeys(Krb5AcceptCredential.java:156)
    at sun.security.jgss.krb5.Krb5Context.acceptSecContext(Krb5Context.java:768)
    at sun.security.jgss.GSSContextImpl.acceptSecContext(GSSContextImpl.java:342)
    at sun.security.jgss.GSSContextImpl.acceptSecContext(GSSContextImpl.java:285)
    at org.atsi.security.kerberos.jaas.common.Kerberos$2.run(Kerberos.java:67)
    at org.atsi.security.kerberos.jaas.common.Kerberos$2.run(Kerberos.java:64)
    at java.security.AccessController.doPrivileged(Native Method)
    at javax.security.auth.Subject.doAsPrivileged(Subject.java:473)
    at org.atsi.security.kerberos.jaas.common.Kerberos.acceptSecurityContext

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points