mina-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Antonio Silvestre (JIRA)" <j...@apache.org>
Subject [jira] [Commented] (DIRMINA-844) Http Proxy Authentication failed to complete (see description for exact point of failure)
Date Wed, 18 May 2016 13:38:13 GMT

    [ https://issues.apache.org/jira/browse/DIRMINA-844?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15288962#comment-15288962

Antonio Silvestre commented on DIRMINA-844:

I had got the same issue. The problem is an error design into the handshake process with an
http authentication required proxy. When we try to connect to the proxy for the first time,
we don't send any authentication header, so we receive a 407 code response, and from the "Proxy-Authenticate"
header we get the required authentication method and set the corresponding AuthHandler class.

The first error is in class "org.apache.mina.proxy.handlers.http.AbstractHttpLogicHandler",
method "", line 377:
    protected HttpProxyResponse decodeResponse(final String response) throws Exception {
        LOGGER.debug("  parseResponse()");

        // Break response into lines
        String[] responseLines = response.split(HttpProxyConstants.CRLF);

        // Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF
        // BUG FIX : Trimed to prevent failures with some proxies that add 
        // extra space chars like "Microsoft-IIS/5.0" ...
        String[] statusLine = responseLines[0].trim().split(" ", 2);

        if (statusLine.length < 2) {
            throw new Exception("Invalid response status line (" + statusLine + "). Response:
" + response);

        // Status code is 3 digits
        if (!statusLine[1].matches("^\\d\\d\\d")) {
            throw new Exception("Invalid response code (" + statusLine[1] + "). Response:
" + response);

        Map<String, List<String>> headers = new HashMap<String, List<String>>();

        for (int i = 1; i < responseLines.length; i++) {
            String[] args = responseLines[i].split(":\\s?", 2);
            StringUtilities.addValueToHeader(headers, args[0], args[1], false);

        return new HttpProxyResponse(statusLine[0], statusLine[1], headers);

The value "statusLine[1]" is expected to be a string starting with the http returned code
(in this case 407) followed by a space and the corresponding message added by the server (as
we're splitting the full status line into only 2 strings). Here you are an example taken from
my company proxy:

{{407 Proxy Authentication Required}}

the regular expression to match "^\\d\\d\\d" is expecting only the ciphers, not the text,
so I've changed this regular expression to add any followed text: "^\\d\\d\\d.*". The HttpProxyResponse
constructor gets the substring from the first 3 chars and parses it to the integer return
code, so the remaining text doesn't affect. Depending of how do you handle this exception,
you may not see the error trace.

After correcting this error, instead of throwing the exception the code goes on and it tries
to reconnect to the proxy, creating a new session and rebuilding the http request to add the
corresponding authentication headers to it, but here there's another problem... The process
never launch the second http request, as the "operationComplete" callback defined into the
"reconnect" method, line 342 is never called:

    private void reconnect(final NextFilter nextFilter, final HttpProxyRequest request) {
        LOGGER.debug("Reconnecting to proxy ...");

        final ProxyIoSession proxyIoSession = getProxyIoSession();

        // Fires reconnection
        proxyIoSession.getConnector().connect(new IoSessionInitializer<ConnectFuture>()
            public void initializeSession(final IoSession session, ConnectFuture future) {
                LOGGER.debug("Initializing new session: {}", session);
                session.setAttribute(ProxyIoSession.PROXY_SESSION, proxyIoSession);
                LOGGER.debug("  setting up proxyIoSession: {}", proxyIoSession);
                future.addListener(new IoFutureListener<ConnectFuture>() {
                    public void operationComplete(ConnectFuture future) {
                        // Reconnection is done so we send the
                        // request to the proxy
                        writeRequest0(nextFilter, request);

The operation is considered "completed" when the handshake phase is completed, but we're into
this phase now, and we need to execute the request to complete it, so here we have a deadlock.
As we haven't completed the handshake phase, we never call the "operationComplete" method
and of course we never do the second http request with the right headers. To solve this problem
we need to remove the custom IoFutureListener and put the inner code into the "initializeSession"
callback directly.

I'm going to make a pull request with this changes. They have been tested and they're working.

> Http Proxy Authentication failed to complete (see description for exact point of failure)
> -----------------------------------------------------------------------------------------
>                 Key: DIRMINA-844
>                 URL: https://issues.apache.org/jira/browse/DIRMINA-844
>             Project: MINA
>          Issue Type: Bug
>          Components: Core
>    Affects Versions: 2.0.3
>         Environment: Mac OS X 10.6.8 
> JDK 1.6
> squid/2.6
> Eclipse
>            Reporter: Parijat Bansal
>             Fix For: 2.0.8
> When trying to connect through an Squid Http Proxy using ProxyConnector (requiring basic
authentication). While debugging issue, I walked through MINA code. Following are my observations:
> 1. First attempt made by MINA do not send any authentication details even though property
set, seems like its to get first response mentioning authentication method. 
> 2. So a second connection is initiated from ProxyConnector and this time request contains
the authentication header. 
> ISSUE: My client kept waiting at this point and it seems that second connection never
got completed. I used eclipse debugger and found that AbstractPollingIoConnector.connect0
method is getting called with proper destination (As I used a NioSocketConnector to construct
ProxyConnector) but after that no progress.
> Also  at Line#343 following were the content of request variable (I wonder if this could
be of help )
> request	AbstractPollingIoConnector$ConnectionRequest  (id=82)	
> 	deadline	1310717009666	
> 	firstListener	null	
> 	handle	SocketChannelImpl  (id=88)	
> 	lock	AbstractPollingIoConnector$ConnectionRequest  (id=82)	
> 	otherListeners	null	
> 	ready	false	
> 	result	null	
> 	session	null	
> 	sessionInitializer	ProxyIoSessionInitializer<T>  (id=104)	
> 	this$0	NioSocketConnector  (id=40)	
> 	waiters	0	

This message was sent by Atlassian JIRA

View raw message