JBoss Community

Re: Security propagation from remote EJB clients to AS7

created by Radek Rodak in JBoss AS 7 Development - View the full discussion

Hi

 

1)

Can you provide client sample code using SASL Security ( for now PLAIN example would be enought ).

 

( or just add this example to https://docs.jboss.org/author/display/AS71/Developer+Guide#DeveloperGuide-EJBinvocationsfromaremoteclientusingJNDI )

 

2)

I looked in source code of  org.jboss.sasl.JBossSaslProvider.java  ( jboss-sasl-1.0.0.Beta9.jar )

 

Ony SASL MECH I see here are:

 

"ANONYMOUS"

"PLAIN",

"DIGEST-MD5",

"JBOSS-LOCAL-USER"

 

Could you also add "GSSAPI"  (  here how to from Darran Lofthouse http://community.jboss.org/wiki/SASLAndKerberos )

 

Basically I would like to do this but with AS7.1:

 

http://community.jboss.org/wiki/EJB3AuthenticationWithSPNEGO

 

I tried to call remote ejb after sucessfull JAAS Login, but JAAS Login Context seams to not get propagatet to Server over Jboss Remote...

 

Here how I tried ( the same Code but calling Web URL Secured with SPNEGO works, so KRB5 Java Setup is ok)  :

 

 

 

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStreamReader;

import java.security.AccessController;

import java.security.Principal;

import java.security.PrivilegedExceptionAction;

import java.security.Security;

import java.util.Collections;

import java.util.Hashtable;

import java.util.Properties;

import java.util.Set;

 

import javax.naming.Context;

import javax.naming.InitialContext;

import javax.naming.NamingException;

import javax.security.auth.Subject;

import javax.security.auth.callback.Callback;

import javax.security.auth.callback.CallbackHandler;

import javax.security.auth.callback.NameCallback;

import javax.security.auth.callback.PasswordCallback;

import javax.security.auth.callback.TextInputCallback;

import javax.security.auth.callback.TextOutputCallback;

import javax.security.auth.callback.UnsupportedCallbackException;

import javax.security.auth.login.LoginContext;

import javax.security.sasl.Sasl;

import javax.security.sasl.SaslClient;

import javax.security.sasl.SaslException;

 

import test.ejb3.TestServiceItf;

 

public class TestServiceClient {

    static String JAAS_CONFIG_ENTRY = "com.sun.security.jgss.krb5.initiate";

    static BufferedReader br = new BufferedReader( new InputStreamReader (System.in));

   

   

   

    public static void main(String[] args) throws Exception {

 

 

        LoginContext lc = null;

        try {

            System.out.println("\n >> Enter Win user Name : ");

            //String callbackUser  = br.readLine ();

            String callbackUser  = "rrad";

            System.out.println("\n >> Enter Win User AD password : ");

           

            //String callbackPwd  = br.readLine ();

            String callbackPwd ="radoslaw13";

            // jaas collback might be needed for ticket refresh...

            lc = new LoginContext(JAAS_CONFIG_ENTRY,new NamePasswordCallbackHandler2(callbackUser,callbackPwd ));

 

            lc.login();

            //and get a subject

            Subject mySubject = lc.getSubject();

            System.out.println(" *********??????????********>>>> subject: "+mySubject);

            Set<Principal> sp = mySubject.getPrincipals();

            if ( sp == null ) System.out.println(" 0 principals ");

            else {

                System.out.println(+sp.size()+" principals");

                for ( Principal p : sp ) {

                    System.out.println("principal name :"+p.getName());

                }

            }

            // in case if not passed to java as property..

            System.setProperty("javax.security.auth.useSubjectCredsOnly", "false");

            System.setProperty( "sun.security.krb5.debug", "true");

                 

           

            PrivilegedExceptionAction<String> action = new GetAction( null, null  );

            //jaas call the service

            String aRet = (String)mySubject.doAs(mySubject, action);

 

            // successfuly called, read returned values

            System.out.println("successfully caled protected Method  : "+aRet);

        } catch (Exception e) {

            e.printStackTrace();

            System.exit(-1);

        }

    }

   

    /**

     *  dummy readLine Helper

     * @return

     */

 

    public static String readLine(String message)

        {

            String s = null;

            System.out.println(message);

            try {

                InputStreamReader converter = new InputStreamReader(System.in);

                BufferedReader in = new BufferedReader(converter);

                s = in.readLine();

            } catch (Exception e) {

                System.out.println("Error! Exception: "+e);

            } finally {

                System.out.println("");

            }

            return s;

        }

   

   

   

    

 

   

}

 

class GetAction implements PrivilegedExceptionAction<String> {

 

    private String toke;

    private String user;

    private String testEjbItf="test.ejb3.TestServiceItf";

    // context.lookup("ejb:" + appName + "/" + moduleName + "/" + distinctName + "/" + beanName + "!" + viewClassName);

    private String testEjbJndi="ejb:/sl-securityTestEjb3//TestServiceSLEJB3Bean!test.ejb3.TestServiceItf";

 

   

    public GetAction(String user , String token) {

        this.user = user;

        this.toke=token;

       

    }

   

    static {

 

        try {

            Sasl.createSaslClient(new String[]{"PLAIN"}, null, "remoting", "ux2084", Collections.EMPTY_MAP, new NamePasswordCallbackHandler2("rrad","radoslaw13" ) );

        } catch (SaslException e) {

            // TODO Auto-generated catch block

            e.printStackTrace();

        }

       

        }

 

    // make shure

    public String run() throws Exception {

       

        //Sasl.createSaslClient(new String[]{"GSSAPI"}, null, "remoting", "ux2084", Collections.EMPTY_MAP, new NamePasswordCallbackHandler2("xxx","yyy" ) );

        //Sasl.createSaslClient(new String[]{"PLAIN"}, null, "remoting", "ux2084", Collections.EMPTY_MAP, new NamePasswordCallbackHandler2("xxx","yyy" ) );

        javax.security.auth.Subject currentSubject = javax.security.auth.Subject.getSubject( AccessController.getContext());

        if ( currentSubject == null ) System.out.println(" our Action runs as Subject: null ");

        else System.out.println(" our Action runs as Subject: "+currentSubject.toString());

        Context ctx = getInitialContext();

        System.out.println("Initial Context created");

        System.out.println("lookup"+testEjbJndi+" @RolesAllowed({\"BackofficeRole\"})");

        Class itfClass = Thread.currentThread().getContextClassLoader().loadClass(testEjbItf);

        TestServiceItf testService = (TestServiceItf)  ctx.lookup(testEjbJndi);

        System.out.println("lookup testEjbJndi successful");

        System.out.println(" call unsecured Method permittAllMethod()");

        Subject asu = testService.permittAllMethod(" calling unsecured");

        System.out.println(" successfully called, received Subject: "+asu);

        System.out.println(" call secured Method with role "+testService.BACKOFFICE_ROLE);

        asu = testService.pwvAuthenticatorSecuredMethod(" calling secured");

        System.out.println(" successfully called, received Subject: "+asu);

        return "Test ok";

    }

 

    private static Context getInitialContext() throws NamingException {

         final Hashtable jndiProperties = new Hashtable();

         jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");

         jndiProperties.put(Context.SECURITY_AUTHENTICATION, "GSSAPI");

         final Context context = new InitialContext(jndiProperties);

         return context;

        }

   

   

}

 

class NamePasswordCallbackHandler2 implements CallbackHandler

{

    /**

     * The username to be provided when prompted.

     */

    private String username;

 

    /**

     * The password to be provided when prompted.

     */

    private String password;

   

    private String url;

 

    /**

     * Create a new NamePasswordCallbackHandler (required Cams default

     * constructor that is dynamically called by the authentication

     * server).

     * @param anURL

     * @param callbackPwd

     * @param callbackUser

     */

    public NamePasswordCallbackHandler2(String callbackUser, String callbackPwd)

    {

        this.username = callbackUser;

        this.password = callbackPwd;

    }

 

 

    /**

     * Set the username.

     *

     * @param username the username to be provided to a NameCallback.

     */

    public void setUsername(String username)

    {

        if (username == null)

        {

            this.username = "";

            return;

        }

 

        this.username = username;

    }

 

    /**

     * Set the password.

     *

     * @param password the password to be provided to a PasswordCallback.

     */

    public void setPassword(String password)

    {

        if (password == null)

        {

            this.password = "";

            return;

        }

 

        this.password = password;

    }

 

    public void handle(Callback[] callbacks)

    throws IOException, UnsupportedCallbackException

  {

    for(int i = 0; i < callbacks.length; i++)

    {

      if(callbacks[i] instanceof TextOutputCallback)

      {

        // Display the message according to the specified type

        TextOutputCallback toc = (TextOutputCallback)callbacks[i];

        switch(toc.getMessageType())

        {

        case TextOutputCallback.INFORMATION:

          log(toc.getMessage());

          break;

        case TextOutputCallback.ERROR:

          log("ERROR: " + toc.getMessage());

          break;

        case TextOutputCallback.WARNING:

          log("WARNING: " + toc.getMessage());

          break;

        default:

          throw new IOException("Unsupported message type: "+toc.getMessageType());

        }

      }

      else if(callbacks[i] instanceof NameCallback)

      {

        // If username not supplied on cmd line, prompt the user for the username.

        NameCallback nc = (NameCallback)callbacks[i];

        if (username == null || username.isEmpty()) {

          System.err.print(nc.getPrompt());

          System.err.flush();

          nc.setName((new BufferedReader(new InputStreamReader(System.in))).readLine());

        }

        else {

          log("username: "+username);

          nc.setName(username);

        }

      }

      else if(callbacks[i] instanceof PasswordCallback)

      {

        PasswordCallback pc = (PasswordCallback)callbacks[i];

       

        // If password not supplied on cmd line, prompt the user for the password.

        if (password == null || password.isEmpty()) {

          System.err.print(pc.getPrompt());

          System.err.flush();

 

          // Note: JAAS specifies that the password is a char[] rather than a String

          String tmpPassword = (new BufferedReader(new InputStreamReader(System.in))).readLine();

          int passLen = tmpPassword.length();

          char[] passwordArray = new char[passLen];

          for(int passIdx = 0; passIdx < passLen; passIdx++)

            passwordArray[passIdx] = tmpPassword.charAt(passIdx);

          pc.setPassword(passwordArray);

        }

        else {

          String tPass = new String();

          for(int p = 0; p < password.length(); p++)

            tPass += "*";

          log("password: "+tPass);

          pc.setPassword(password.toCharArray());

        }       

      }

      else if(callbacks[i] instanceof TextInputCallback)

      {

        // Prompt the user for the username

        TextInputCallback callback = (TextInputCallback)callbacks[i];

        System.err.print(callback.getPrompt());

        System.err.flush();

        callback.setText((new BufferedReader(new InputStreamReader(System.in))).readLine());

      }

      else

      {

        throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback");

      }

    }

  }

 

  private void log(String str) { System.out.println(str); }

 

 

Happy New Year

 

Radek Rodak

Reply to this message by going to Community

Start a new discussion in JBoss AS 7 Development at Community