[
https://issues.apache.org/jira/browse/JENA-2011?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Alexander Radzin updated JENA-2011:
-----------------------------------
Description:
h1. Description
Start fuseki server on IPv6 environment and navigate browser to
[http://localhost:3030|http://localhost:3030/].
The UI does not show any datasets and all attempts to do anything with UI fail.
Press F12 (dev tools) in your browser and see that GET request to `$/server`
returns with error status 403 Forbidden.
h1. Analysis
The discovery shows the following problem. The status is set by
{{org.apache.jena.fuseki.authz.LocalhostFilter}}: {{isAccessAllowed()}} returns
`false`.
This happens in turn because the {{remoteAddr}} should be one of
{{0:0:0:0:0:0:0:1}} or {{127.0.0.1}}.
Now let's take a look on code in `org.eclipse.jetty.server.Request`
(implementation of `HttpServletRequest` used in Jetty):
{code:java}
public String getRemoteAddr() {
..............................................
// Add IPv6 brackets if necessary, to be consistent
// with cases where _remote has been built from other
// sources such as forward headers or PROXY protocol.
return HostPort.normalizeHost(result);
}
{code}
(I put here only the relevant part).
Now let's review {{HostPort.normalizeHost}}:
{code:java}
public static String normalizeHost(String host)
{
// if it is normalized IPv6 or could not be IPv6, return
if (host.isEmpty() || host.charAt(0) == '[' || host.indexOf(':') < 0)
return host;
// normalize with [ ]
return "[" + host + "]";
}
{code}
In case of IPv6 we this function wraps the address using squire brackets, i.e.
address {{0:0:0:0:0:0:0:1}} becomes {{[0:0:0:0:0:0:0:1]}}. However jumping back
to the {{LocalhostFilter.isAccessAllowed()}} the wrapped string is compared to
unwrapped one that causes {{isAccessAllowed}} to return false.
h1. Suggested fix
Since wrapping of the address with squire brackets is the Jetty specific we
cannot just changes string {{"0:0:0:0:0:0:0:1"}} to {{"[0:0:0:0:0:0:0:1]"}} in
{{LocalhostFilter}} because such change might break this code in other
environments. However taking in cosideration comment in
{{HostPort.normalizeHost}}:
{code:java}
* Normalizes IPv6 address as per https://tools.ietf.org/html/rfc2732
* and https://tools.ietf.org/html/rfc6874,
* surrounding with square brackets if they are absent.
{code}
we can assume that such format is "standard" and just add wrapped version of
this IP to {{LocalhostFilter}}:
{code:java}
private static final Collection<String> localhosts = new
HashSet<>(Arrays.asList(LOCALHOST_IpV4, LOCALHOST_IpV6, "[" +LOCALHOST_IpV4 +
"]"));
protected boolean isAccessAllowed(ServletRequest request, ServletResponse
response, Object mappedValue) throws Exception {
return localhosts.contains(request.getRemoteAddr());
}
{code}
h1. Workaround
Current workaround is to fix file {{shiro.ini}}: just uncomment line
{code}
##/$/** = anon
{code}
This grant permission to anonymous user to access to access all APIs (that
start with {{$}}).
was:
h1. Description
Start fuseki server on IPv6 environment and navigate browser to
[http://localhost:3030|http://localhost:3030/].
The UI does not show any datasets and all attempts to do anything with UI fail.
Press F12 (dev tools) in your browser and see that GET request to `$/server`
returns with error status 403 Forbidden.
h1. Analysis
The discovery shows the following problem. The status is set by
{{org.apache.jena.fuseki.authz.LocalhostFilter}}: {{isAccessAllowed()}} returns
`false`.
This happens in turn because the {{remoteAddr}} should be one of
{{0:0:0:0:0:0:0:1}} or {{127.0.0.1}}.
Now let's take a look on code in `org.eclipse.jetty.server.Request`
(implementation of `HttpServletRequest` used in Jetty):
{code:java}
public String getRemoteAddr() {
..............................................
// Add IPv6 brackets if necessary, to be consistent
// with cases where _remote has been built from other
// sources such as forward headers or PROXY protocol.
return HostPort.normalizeHost(result);
}
{code}
(I put here only the relevant part).
Now let's review {{HostPort.normalizeHost}}:
{code:java}
public static String normalizeHost(String host)
{
// if it is normalized IPv6 or could not be IPv6, return
if (host.isEmpty() || host.charAt(0) == '[' || host.indexOf(':') < 0)
return host;
// normalize with [ ]
return "[" + host + "]";
}
{code}
In case of IPv6 we this function wraps the address using squire brackets, i.e.
address {{0:0:0:0:0:0:0:1}} becomes {{[0:0:0:0:0:0:0:1]}}. However jumping back
to the {{LocalhostFilter.isAccessAllowed()}} the wrapped string is compared to
unwrapped one that causes {{isAccessAllowed}} to return false.
h1. Suggested fix
Since wrapping of the address with squire brackets is the Jetty specific we
cannot just changes string {{"0:0:0:0:0:0:0:1"}} to {{"[0:0:0:0:0:0:0:1]"}} in
{{LocalhostFilter}} because such change might break this code in other
environments. However taking in cosideration comment in
{{HostPort.normalizeHost}}:
{code:java}
* Normalizes IPv6 address as per https://tools.ietf.org/html/rfc2732
* and https://tools.ietf.org/html/rfc6874,
* surrounding with square brackets if they are absent.
{code}
we can assume that such format is "standard" and just add wrapped version of
this IP to {{LocalhostFilter}}:
{code:java}
private static final Collection<String> localhosts = new
HashSet<>(Arrays.asList(LOCALHOST_IpV4, LOCALHOST_IpV6, "[" +LOCALHOST_IpV4 +
"]"));
protected boolean isAccessAllowed(ServletRequest request, ServletResponse
response, Object mappedValue) throws Exception {
return localhosts.contains(request.getRemoteAddr());
}
{code}
> Fuseki does not work in IPv6 environment with Jetty
> ---------------------------------------------------
>
> Key: JENA-2011
> URL: https://issues.apache.org/jira/browse/JENA-2011
> Project: Apache Jena
> Issue Type: Bug
> Components: Fuseki
> Affects Versions: Jena 3.17.0
> Environment: Tested on both Linux (with JDK 13) and Windows (with JDK
> 15)
> Reporter: Alexander Radzin
> Priority: Major
> Original Estimate: 1h
> Remaining Estimate: 1h
>
> h1. Description
> Start fuseki server on IPv6 environment and navigate browser to
> [http://localhost:3030|http://localhost:3030/].
> The UI does not show any datasets and all attempts to do anything with UI
> fail. Press F12 (dev tools) in your browser and see that GET request to
> `$/server` returns with error status 403 Forbidden.
> h1. Analysis
> The discovery shows the following problem. The status is set by
> {{org.apache.jena.fuseki.authz.LocalhostFilter}}: {{isAccessAllowed()}}
> returns `false`.
> This happens in turn because the {{remoteAddr}} should be one of
> {{0:0:0:0:0:0:0:1}} or {{127.0.0.1}}.
> Now let's take a look on code in `org.eclipse.jetty.server.Request`
> (implementation of `HttpServletRequest` used in Jetty):
> {code:java}
> public String getRemoteAddr() {
> ..............................................
> // Add IPv6 brackets if necessary, to be consistent
> // with cases where _remote has been built from other
> // sources such as forward headers or PROXY protocol.
> return HostPort.normalizeHost(result);
> }
> {code}
> (I put here only the relevant part).
> Now let's review {{HostPort.normalizeHost}}:
> {code:java}
> public static String normalizeHost(String host)
> {
> // if it is normalized IPv6 or could not be IPv6, return
> if (host.isEmpty() || host.charAt(0) == '[' || host.indexOf(':') < 0)
> return host;
> // normalize with [ ]
> return "[" + host + "]";
> }
> {code}
> In case of IPv6 we this function wraps the address using squire brackets,
> i.e. address {{0:0:0:0:0:0:0:1}} becomes {{[0:0:0:0:0:0:0:1]}}. However
> jumping back to the {{LocalhostFilter.isAccessAllowed()}} the wrapped string
> is compared to unwrapped one that causes {{isAccessAllowed}} to return false.
> h1. Suggested fix
> Since wrapping of the address with squire brackets is the Jetty specific we
> cannot just changes string {{"0:0:0:0:0:0:0:1"}} to {{"[0:0:0:0:0:0:0:1]"}}
> in {{LocalhostFilter}} because such change might break this code in other
> environments. However taking in cosideration comment in
> {{HostPort.normalizeHost}}:
> {code:java}
> * Normalizes IPv6 address as per https://tools.ietf.org/html/rfc2732
> * and https://tools.ietf.org/html/rfc6874,
> * surrounding with square brackets if they are absent.
> {code}
> we can assume that such format is "standard" and just add wrapped version of
> this IP to {{LocalhostFilter}}:
> {code:java}
> private static final Collection<String> localhosts = new
> HashSet<>(Arrays.asList(LOCALHOST_IpV4, LOCALHOST_IpV6, "[" +LOCALHOST_IpV4 +
> "]"));
> protected boolean isAccessAllowed(ServletRequest request, ServletResponse
> response, Object mappedValue) throws Exception {
> return localhosts.contains(request.getRemoteAddr());
> }
> {code}
> h1. Workaround
> Current workaround is to fix file {{shiro.ini}}: just uncomment line
> {code}
> ##/$/** = anon
> {code}
> This grant permission to anonymous user to access to access all APIs (that
> start with {{$}}).
--
This message was sent by Atlassian Jira
(v8.3.4#803005)