MixedAuthenticator overrides final method start.()V

Oct 21, 2010 at 4:22 PM

Hello,

 

I am using Waffle 1.4, pasted the necessary libraries (as mentioned in the tutorial on mixed mode) into the the lib folder of Tomcat 6 and received the following mesages after restarting

Tomcat.

java.lang.VerifyError: class waffle.apache.MixedAuthenticator overrides final method start.()V

I was not able to bug fix this error  as the source of version 1.4 seems to have undocumented dependencies. Though one dependeny is mentioned which is

the spring security framework  it is pretty much unclear to me how to get this library version 1.4  as  the link does not  guide me in order to be able to download this library.

Further the library version seems not to be available on the web site of spring framework. Only the new version like 2.x which has further dependencies and requires  implemeting

classes to implement its abstract methods. May be my approach is totally wrong.

Has anybody a simple solution to this problem?

Regards,

vandunen

 

 

Coordinator
Oct 21, 2010 at 9:07 PM

What exact version of Tomcat are you using? The 1.4 release was compiled against 6.0.29, maybe it has something to do with it?

MixedAuthenticator doesn't have any dependencies on spring framework. Waffle is a collection of filters: servlets, tomcat, spring, etc., each filter has its own dependencies. We package all Waffle filters it into a single JAR for convenience, but you dn't need the unused filters and their dependencies at runtime.

Oct 22, 2010 at 9:39 AM

I'm using apache-tomcat-6.0.29.

The following displays the source code of MixedAuthenticator 1.4 which does override methods which are meant to be final according to Tomcat

How could that happen? Is Tomcat or am I using  the wrong libraries?

 

/**
 * Mixed Negotiate + Form Authenticator.
 * @author dblock[at]dblock[dot]org
 */
public class MixedAuthenticator extends WaffleAuthenticatorBase {

    public MixedAuthenticator() {
        super();
        _log = LogFactory.getLog(MixedAuthenticator.class);
        _info = "waffle.apache.MixedAuthenticator/1.0";
        _log.debug("[waffle.apache.MixedAuthenticator] loaded");
    }

    @Override
    public void start() {
        _log.info("[waffle.apache.MixedAuthenticator] started");       
    }
   
    @Override
    public void stop() {
        _log.info("[waffle.apache.MixedAuthenticator] stopped");       
    }

    @Override
    protected boolean authenticate(Request request, Response response, LoginConfig loginConfig) {

        // realm: fail if no realm is configured
        if(context == null || context.getRealm() == null) {
            _log.warn("missing context/realm");
            sendError(response, HttpServletResponse.SC_SERVICE_UNAVAILABLE);
            return false;
        }

        _log.debug(request.getMethod() + " " + request.getRequestURI() + ", contentlength: " + request.getContentLength());
       
        String queryString = request.getQueryString();
        boolean negotiateCheck = (queryString != null && queryString.equals("j_negotiate_check"));
        _log.debug("negotiateCheck: " + negotiateCheck + " (" +  ((queryString == null) ? "<none>" : queryString) + ")");
        boolean securityCheck = (queryString != null && queryString.equals("j_security_check"));
        _log.debug("securityCheck: " + securityCheck + " (" +  ((queryString == null) ? "<none>" : queryString) + ")");

        Principal principal = request.getUserPrincipal();
       
        AuthorizationHeader authorizationHeader = new AuthorizationHeader(request);       
        boolean ntlmPost = authorizationHeader.isNtlmType1PostAuthorizationHeader();
        _log.debug("authorization: " + authorizationHeader.toString() + ", ntlm post: " + ntlmPost);
   
        if (principal != null && ! ntlmPost) {
            _log.debug("previously authenticated user: " + principal.getName());
            return true;
        } else if (negotiateCheck) {
            if (! authorizationHeader.isNull()) {
                return negotiate(request, response, authorizationHeader);
            } else {
                _log.debug("authorization required");
                sendUnauthorized(response);
                return false;
            }
        } else if (securityCheck) {
            boolean postResult = post(request, response, loginConfig);
            if (postResult) {
                redirectTo(request, response, request.getServletPath());
            } else {
                redirectTo(request, response, loginConfig.getErrorPage());
            }
            return postResult;
        } else {
            redirectTo(request, response, loginConfig.getLoginPage());
            return false;
        }
    }
   
    private boolean negotiate(Request request, Response response, AuthorizationHeader authorizationHeader) {

        String securityPackage = authorizationHeader.getSecurityPackage();           
        // maintain a connection-based session for NTLM tokens
        String connectionId = NtlmServletRequest.getConnectionId(request);
       
        _log.debug("security package: " + securityPackage + ", connection id: " + connectionId);
       
        boolean ntlmPost = authorizationHeader.isNtlmType1PostAuthorizationHeader();
       
        if (ntlmPost) {
            // type 1 NTLM authentication message received
            _auth.resetSecurityToken(connectionId);
        }
       
        // log the user in using the token
        IWindowsSecurityContext securityContext = null;
       
        try {
            byte[] tokenBuffer = authorizationHeader.getTokenBytes();
            _log.debug("token buffer: " + tokenBuffer.length + " byte(s)");
            securityContext = _auth.acceptSecurityToken(connectionId, tokenBuffer, securityPackage);
            _log.debug("continue required: " + securityContext.getContinue());

            byte[] continueTokenBytes = securityContext.getToken();
            if (continueTokenBytes != null) {
                String continueToken = new String(Base64.encode(continueTokenBytes));
                _log.debug("continue token: " + continueToken);
                response.addHeader("WWW-Authenticate", securityPackage + " " + continueToken);
            }
           
            if (securityContext.getContinue() || ntlmPost) {
                response.setHeader("Connection", "keep-alive");
                response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
                response.flushBuffer();
                return false;
            }
           
        } catch (Exception e) {
            _log.warn("error logging in user: " + e.getMessage());
            sendUnauthorized(response);
            return false;
        }
       
        // create and register the user principal with the session
        IWindowsIdentity windowsIdentity = securityContext.getIdentity();
       
        // disable guest login
        if (! _allowGuestLogin && windowsIdentity.isGuest()) {
            _log.warn("guest login disabled: " + windowsIdentity.getFqn());
            sendUnauthorized(response);
            return false;           
        }
       
        try {
           
            _log.debug("logged in user: " + windowsIdentity.getFqn() +
                    " (" + windowsIdentity.getSidString() + ")");
           
            GenericWindowsPrincipal windowsPrincipal = new GenericWindowsPrincipal(
                    windowsIdentity, context.getRealm(), _principalFormat, _roleFormat);
           
            _log.debug("roles: " + windowsPrincipal.getRolesString());
   
            // create a session associated with this request if there's none
            HttpSession session = request.getSession(true);
            _log.debug("session id:" + session.getId());

            register(request, response, windowsPrincipal, securityPackage, windowsPrincipal.getName(), null);
            _log.info("successfully logged in user: " + windowsPrincipal.getName());
           
        } finally {
            windowsIdentity.dispose();
        }
       
        return true;
    }
   
    private boolean post(Request request, Response response, LoginConfig loginConfig) {
       
        String username = request.getParameter("j_username");
        String password = request.getParameter("j_password");
       
        _log.debug("logging in: " + username);
       
        IWindowsIdentity windowsIdentity = null;
        try {
            windowsIdentity = _auth.logonUser(username, password);
        } catch (Exception e) {
            _log.error(e.getMessage());
            return false;
        }

        // disable guest login
        if (! _allowGuestLogin && windowsIdentity.isGuest()) {
            _log.warn("guest login disabled: " + windowsIdentity.getFqn());
            return false;
        }
       
        try {
            _log.debug("successfully logged in " + username + " (" + windowsIdentity.getSidString() + ")");      
           
            GenericWindowsPrincipal windowsPrincipal = new GenericWindowsPrincipal(
                    windowsIdentity, context.getRealm(), _principalFormat, _roleFormat);
           
            _log.debug("roles: " + windowsPrincipal.getRolesString());
           
            // create a session associated with this request if there's none
            HttpSession session = request.getSession(true);
            _log.debug("session id:" + session.getId());

            register(request, response, windowsPrincipal, "FORM", windowsPrincipal.getName(), null);
            _log.info("successfully logged in user: " + windowsPrincipal.getName());
        } finally {
            windowsIdentity.dispose();
        }
       
        return true;
    }
   
    private void redirectTo(Request request, Response response, String url) {
        try {
            _log.debug("redirecting to: " + url);
            ServletContext servletContext = context.getServletContext();
            RequestDispatcher disp = servletContext.getRequestDispatcher(url);
            disp.forward(request.getRequest(), response);
        } catch (IOException e) {
            _log.error(e.getMessage());
            throw new RuntimeException(e);
        } catch (ServletException e) {
            _log.error(e.getMessage());
            throw new RuntimeException(e);
        }       
    }
}

 

 

Coordinator
Oct 22, 2010 at 1:15 PM

Something is wrong. In Tomcat 6 this method is declared public void (I checked out the latest source code), there's no final on it, and it's meant to be overridden. Not that it matters for our filter, start could be safely removed, it doesn't do anything.

One other thing I could think about - which version of Java runtime do you have?

I think you should do two things.

  1. Take a stock Tomcat 6.0.29 out of the box with no changes and add jna.jar, platform.jar commons-logging-1.1.jar, guava...jar and waffle-jna.jar from 1.4. Confirm that you have the same problem.
  2. Finish setting up the development environment. Get the source from SVN. You should be able to import waffle projects into Eclipse, compile the whole thing with ANT without any problems, etc. This will let you experiment with things like removing the override on start.

 

Oct 22, 2010 at 5:52 PM

Ok,

 I will do as you say and inform you next week

Oct 26, 2010 at 3:50 PM

I used a clean Tomcat 6.0.29 and pasted the aforementioned libraries into the lib directory of Tomcat and it worked fine so I cannot confirm to have the same problem.

Thank you.

I had used Tomcat 7.0 invoked by NetBeans 6.10M under Windows XP

What concerns you advisory 2  I am working on it and will report later.

 

 

 

 

 

 

 

 

 

Coordinator
Oct 26, 2010 at 6:31 PM

Okay, these authenticators don't support Tomcat 7 as of now. There's a known feature request for this - http://waffle.codeplex.com/workitem/9644. It's going to be quite a bit of work to support all versions of Tomcat in a single package, I have to implement some kind of provider interface. If you want to do some work, make a patch for current waffle trunk with all the code changes for Tomcat 7. Update ThirdParty/Tomcat with tomcat 7 and make the code changes. Attach the patch to the feature request above. I would commit that to a branch.

Coordinator
Nov 1, 2010 at 5:57 PM

I've created a branch for Tomcat 7, made all the code changes, and uploaded a build to http://waffle.codeplex.com/releases/view/54962.

Nov 2, 2010 at 10:17 PM

Thanks.

That's a great thing to know!

Source code: After I isolated the package with the authenticators i did not have anymore the trouble with the aforementioned dependencies.

But I would like to check out the branch created by you as Tomcat 7.0 is really my targeted application server respectively servlet container.

Let's get to work