I'll give it a shot.  Running into some trouble getting stock tests to pass on 
Mac OS and separate problems behind a corporate proxy.  Spinning a Linux VM on 
the open WiFi to try.

FWIW, we're not using multicast for this.  I just looks like 
HttpConnectionFactory calls the URI utility methods physically located in the 
static URI class on MulticastConnectionFactory.  Otherwise this is https with 
sticky failover.

-Zac

> On Sep 20, 2017, at 12:50, Romain Manni-Bucau <rmannibu...@gmail.com> wrote:
> 
> Hi Zachary
> 
> 
> We have some coverage for it in
> https://github.com/apache/tomee/blob/master/server/openejb-client/src/test/java/org/apache/openejb/client/HttpConnectionTest.java
> 
> Multicast not being used that often with http (more likely with ejbd) we
> didnt test it, do you want to try to add a test and fix?
> 
> Le 20 sept. 2017 18:28, "Zachary Bedell" <zbed...@nycourts.gov> a écrit :
> 
> Greetings all,
> 
> Pretty sure I found a bug in the way
> org.apache.openejb.client.MulticastConnectionFactory
> decodes URL parameters.  The final result of the issue is that if you use
> HTTP basic authentication when calling ServerServlet and
> openejb.ejbd.authenticate-with-request=true, you can't login with a
> password that contains an ampersand character.
> 
> The flow looks something like:
> 
> 1) Create a new IntitialContext with PROVIDER_URL set to
> failover:sticky+random:https://myserver/ejb/invoke?basic.
> username=xyz&basic.password=pass%26word
>  a) /ejb/invoke is where I have org.apache.openejb.server.httpd.ServerServlet
> mapped
>  b) web.xml on that mapping requires BASIC auth.
>  c) key part of URL is the literal password "pass&word" URL encoded with
> ampersand -> %26
> 
> 2) TomEE internals eventually end up at HttpConnectionFactory$HttpConnection's
> constructor where line 76 calls:
>        params = MulticastConnectionFactory.URIs.parseParamters(uri);
>        By this time, various unwrapping has paired the URL down to:
>        https://myserver/ejb/invoke?basic.username=xyz&basic.
> password=pass%26word
> 
> 3) MulticastConnectionFactory...parseParameters, IE line 136:
>        return uri.getQuery() == null ? new HashMap<String, String>(0) :
> parseQuery(stripPrefix(uri.getQuery(), "?"));
> 
> That calls URI.getQuery() which decodes the URI's query string, then passes
> that into parseQuery() which splits up the query parameters delimited by
> ampersands.  The call to URI.getQuery() is the problem.  For the above URI,
> the result is:
>        basic.username=xyz&basic.password=pass&word
>        The ampersand in the query parameter basic.password is decoded and
> then indistinguishable from a query parameter separator.  When passed into
> parseQuery, the resulting value for basic.password is just "pass".
> 
> Since MulticastConnectionFactory$URIs::parseQuery already calls
> URLDecoder.decode() on both name and value pairs, the call in
> parseParameters should be to URI::getRawQuery() instead of getQuery().  I
> think there's also a possible double decoding issue here which could
> corrupt certain values by decoding the value a second time.
> 
> For the time being, I think I can work around this by passing the
> authorization query parameter with the user:pass already base64 encoded.
> Pretty sure this should be a complete & safe fix:
> 
> 
> diff --git a/server/openejb-client/src/main/java/org/apache/openejb/client/
> MulticastConnectionFactory.java b/server/openejb-client/src/
> main/java/org/apache/openejb/client/MulticastConnectionFactory.java
> index 22f2f86a6a..eedb54840e 100644
> --- a/server/openejb-client/src/main/java/org/apache/openejb/client/
> MulticastConnectionFactory.java
> +++ b/server/openejb-client/src/main/java/org/apache/openejb/client/
> MulticastConnectionFactory.java
> @@ -133,7 +133,7 @@ public class MulticastConnectionFactory implements
> ConnectionFactory {
>         }
> 
>         public static Map<String, String> parseParamters(final URI uri)
> throws URISyntaxException {
> -            return uri.getQuery() == null ? new HashMap<String, String>(0)
> : parseQuery(stripPrefix(uri.getQuery(), "?"));
> +            return uri.getQuery() == null ? new HashMap<String, String>(0)
> : parseQuery(stripPrefix(uri.getRawQuery(), "?"));
>         }
> 
>         public static String stripPrefix(final String value, final String
> prefix) {
> 
> 
> 
> Best regards,
> Zac Bedell

Attachment: signature.asc
Description: Message signed with OpenPGP

Reply via email to