All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.undertow.server.handlers.SSLHeaderHandler Maven / Gradle / Ivy

There is a newer version: 2.3.18.Final
Show newest version
/*
 * JBoss, Home of Professional Open Source.
 * Copyright 2014 Red Hat, Inc., and individual contributors
 * as indicated by the @author tags.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package io.undertow.server.handlers;

import io.undertow.UndertowLogger;
import io.undertow.server.BasicSSLSessionInfo;
import io.undertow.server.ExchangeCompletionListener;
import io.undertow.server.HandlerWrapper;
import io.undertow.server.HttpHandler;
import io.undertow.server.HttpServerExchange;
import io.undertow.server.SSLSessionInfo;
import io.undertow.server.handlers.builder.HandlerBuilder;
import io.undertow.util.Certificates;
import io.undertow.util.HeaderMap;

import javax.security.cert.CertificateException;

import static io.undertow.util.Headers.SSL_CIPHER;
import static io.undertow.util.Headers.SSL_CIPHER_USEKEYSIZE;
import static io.undertow.util.Headers.SSL_CLIENT_CERT;
import static io.undertow.util.Headers.SSL_SESSION_ID;

import java.util.Collections;
import java.util.Map;
import java.util.Set;

/**
 * Handler that sets SSL information on the connection based on the following headers:
 * 

*

    *
  • SSL_CLIENT_CERT
  • *
  • SSL_CIPHER
  • *
  • SSL_SESSION_ID
  • *
*

* If this handler is present in the chain it will always override the SSL session information, * even if these headers are not present. *

* This handler MUST only be used on servers that are behind a reverse proxy, where the reverse proxy * has been configured to always set these header for EVERY request (or strip existing headers with these * names if no SSL information is present). Otherwise it may be possible for a malicious client to spoof * a SSL connection. * * @author Stuart Douglas */ public class SSLHeaderHandler implements HttpHandler { public static final String HTTPS = "https"; private static final String NULL_VALUE = "(null)"; private static final ExchangeCompletionListener CLEAR_SSL_LISTENER = new ExchangeCompletionListener() { @Override public void exchangeEvent(HttpServerExchange exchange, NextListener nextListener) { exchange.getConnection().setSslSessionInfo(null); nextListener.proceed(); } }; private final HttpHandler next; public SSLHeaderHandler(HttpHandler next) { this.next = next; } @Override public void handleRequest(HttpServerExchange exchange) throws Exception { HeaderMap requestHeaders = exchange.getRequestHeaders(); final String sessionId = requestHeaders.getFirst(SSL_SESSION_ID); final String cipher = requestHeaders.getFirst(SSL_CIPHER); String clientCert = requestHeaders.getFirst(SSL_CLIENT_CERT); String keySizeStr = requestHeaders.getFirst(SSL_CIPHER_USEKEYSIZE); Integer keySize = null; if (keySizeStr != null) { try { keySize = Integer.parseUnsignedInt(keySizeStr); } catch (NumberFormatException e) { UndertowLogger.REQUEST_LOGGER.debugf("Invalid SSL_CIPHER_USEKEYSIZE header %s", keySizeStr); } } if (clientCert != null || sessionId != null || cipher != null) { if (clientCert != null) { if (clientCert.isEmpty() || clientCert.equals(NULL_VALUE)) { // SSL is in place but client cert was not sent clientCert = null; } else if (clientCert.length() > 28 + 26) { // the proxy client replaces \n with ' ' StringBuilder sb = new StringBuilder(clientCert.length() + 1); sb.append(Certificates.BEGIN_CERT); sb.append('\n'); sb.append(clientCert.replace(' ', '\n').substring(28, clientCert.length() - 26));//core certificate data sb.append('\n'); sb.append(Certificates.END_CERT); clientCert = sb.toString(); } } try { SSLSessionInfo info = new BasicSSLSessionInfo(sessionId, cipher, clientCert, keySize); exchange.setRequestScheme(HTTPS); exchange.getConnection().setSslSessionInfo(info); exchange.addExchangeCompleteListener(CLEAR_SSL_LISTENER); } catch (java.security.cert.CertificateException | CertificateException e) { UndertowLogger.REQUEST_LOGGER.debugf(e, "Could not create certificate from header %s", clientCert); } } next.handleRequest(exchange); } @Override public String toString() { return "ssl-headers()"; } public static class Builder implements HandlerBuilder { @Override public String name() { return "ssl-headers"; } @Override public Map> parameters() { return Collections.emptyMap(); } @Override public Set requiredParameters() { return Collections.emptySet(); } @Override public String defaultParameter() { return null; } @Override public HandlerWrapper build(Map config) { return new Wrapper(); } } private static class Wrapper implements HandlerWrapper { @Override public HttpHandler wrap(HttpHandler handler) { return new SSLHeaderHandler(handler); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy