Issue #3462 - fix server validation of websocket upgrade response
Signed-off-by: lachan-roberts <lachlan@webtide.com>
This commit is contained in:
parent
53a4a747db
commit
1a20c8cda3
|
@ -43,6 +43,7 @@ import org.eclipse.jetty.server.Response;
|
||||||
import org.eclipse.jetty.util.log.Log;
|
import org.eclipse.jetty.util.log.Log;
|
||||||
import org.eclipse.jetty.util.log.Logger;
|
import org.eclipse.jetty.util.log.Logger;
|
||||||
import org.eclipse.jetty.websocket.core.Behavior;
|
import org.eclipse.jetty.websocket.core.Behavior;
|
||||||
|
import org.eclipse.jetty.websocket.core.ExtensionConfig;
|
||||||
import org.eclipse.jetty.websocket.core.FrameHandler;
|
import org.eclipse.jetty.websocket.core.FrameHandler;
|
||||||
import org.eclipse.jetty.websocket.core.WebSocketConstants;
|
import org.eclipse.jetty.websocket.core.WebSocketConstants;
|
||||||
import org.eclipse.jetty.websocket.core.internal.Negotiated;
|
import org.eclipse.jetty.websocket.core.internal.Negotiated;
|
||||||
|
@ -60,9 +61,8 @@ public final class RFC6455Handshaker implements Handshaker
|
||||||
private static final HttpField CONNECTION_UPGRADE = new PreEncodedHttpField(HttpHeader.CONNECTION, HttpHeader.UPGRADE.asString());
|
private static final HttpField CONNECTION_UPGRADE = new PreEncodedHttpField(HttpHeader.CONNECTION, HttpHeader.UPGRADE.asString());
|
||||||
private static final HttpField SERVER_VERSION = new PreEncodedHttpField(HttpHeader.SERVER, HttpConfiguration.SERVER_VERSION);
|
private static final HttpField SERVER_VERSION = new PreEncodedHttpField(HttpHeader.SERVER, HttpConfiguration.SERVER_VERSION);
|
||||||
|
|
||||||
public boolean upgradeRequest(WebSocketNegotiator negotiator, HttpServletRequest request,
|
public boolean upgradeRequest(WebSocketNegotiator negotiator, HttpServletRequest request, HttpServletResponse response,
|
||||||
HttpServletResponse response,
|
FrameHandler.Customizer defaultCustomizer) throws IOException
|
||||||
FrameHandler.Customizer defaultCustomizer) throws IOException
|
|
||||||
{
|
{
|
||||||
Request baseRequest = Request.getBaseRequest(request);
|
Request baseRequest = Request.getBaseRequest(request);
|
||||||
HttpChannel httpChannel = baseRequest.getHttpChannel();
|
HttpChannel httpChannel = baseRequest.getHttpChannel();
|
||||||
|
@ -153,22 +153,42 @@ public final class RFC6455Handshaker implements Handshaker
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if subprotocol negotiated
|
// validate negotiated subprotocol
|
||||||
String subprotocol = negotiation.getSubprotocol();
|
String subprotocol = negotiation.getSubprotocol();
|
||||||
if (negotiation.getOfferedSubprotocols().size() > 0)
|
if (subprotocol != null)
|
||||||
{
|
{
|
||||||
if (subprotocol == null)
|
|
||||||
{
|
|
||||||
// TODO: this message needs to be returned to Http Client
|
|
||||||
LOG.warn("not upgraded: no subprotocol selected from offered subprotocols {}: {}", negotiation.getOfferedSubprotocols(), baseRequest);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!negotiation.getOfferedSubprotocols().contains(subprotocol))
|
if (!negotiation.getOfferedSubprotocols().contains(subprotocol))
|
||||||
{
|
{
|
||||||
// TODO: this message needs to be returned to Http Client
|
// TODO: this message needs to be returned to Http Client
|
||||||
LOG.warn("not upgraded: selected subprotocol {} not present in offered subprotocols {}: {}", subprotocol, negotiation.getOfferedSubprotocols(),
|
LOG.warn("not upgraded: selected subprotocol {} not present in offered subprotocols {}: {}",
|
||||||
baseRequest);
|
subprotocol, negotiation.getOfferedSubprotocols(), baseRequest);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!negotiation.getOfferedSubprotocols().isEmpty())
|
||||||
|
{
|
||||||
|
// TODO: this message needs to be returned to Http Client
|
||||||
|
LOG.warn("not upgraded: no subprotocol selected from offered subprotocols {}: {}",
|
||||||
|
negotiation.getOfferedSubprotocols(), baseRequest);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// validate negotiated extensions
|
||||||
|
negotiation.getOfferedExtensions();
|
||||||
|
for (ExtensionConfig config : negotiation.getNegotiatedExtensions())
|
||||||
|
{
|
||||||
|
long numMatch = negotiation.getOfferedExtensions().stream().filter(c -> config.getName().equalsIgnoreCase(c.getName())).count();
|
||||||
|
if (numMatch < 1)
|
||||||
|
{
|
||||||
|
LOG.warn("Upgrade failed: negotiated extension not requested {}: {}", config.getName(), baseRequest);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (numMatch > 1)
|
||||||
|
{
|
||||||
|
LOG.warn("Upgrade failed: multiple negotiated extensions of the same name {}: {}", config.getName(), baseRequest);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue