Commit f1795934 authored by Tobias Wich's avatar Tobias Wich
Browse files

Implement HTTPS binding

parent 7b2c6068
......@@ -19,3 +19,5 @@ test-output
.libs/
project.properties
LICENSE.Open-eCard
/bindings/http/src/main/resources/binding/server-keystore.p12
/bindings/http/keypass
......@@ -55,11 +55,11 @@ import org.openecard.crypto.tls.proxy.ProxySettings;
import org.openecard.common.util.FileUtils;
import org.openecard.common.util.Pair;
import org.openecard.common.util.TR03112Utils;
import org.openecard.crypto.common.ReusableSecureRandom;
import org.openecard.transport.httpcore.cookies.CookieException;
import org.openecard.transport.httpcore.cookies.CookieManager;
import org.openecard.crypto.tls.ClientCertDefaultTlsClient;
import org.openecard.crypto.tls.ClientCertTlsClient;
import org.openecard.crypto.tls.ReusableSecureRandom;
import org.openecard.crypto.tls.auth.DynamicAuthentication;
import org.openecard.transport.httpcore.HttpRequestHelper;
import org.openecard.transport.httpcore.HttpUtils;
......
......@@ -50,7 +50,7 @@ import org.openecard.crypto.tls.proxy.ProxySettings;
import static org.openecard.binding.tctoken.ex.ErrorTranslations.*;
import org.openecard.common.OpenecardProperties;
import org.openecard.common.util.UrlBuilder;
import org.openecard.crypto.tls.ReusableSecureRandom;
import org.openecard.crypto.common.ReusableSecureRandom;
/**
......
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.openecard</groupId>
<artifactId>bindings</artifactId>
<version>1.1.0-SNAPSHOT</version>
</parent>
<parent>
<groupId>org.openecard</groupId>
<artifactId>bindings</artifactId>
<version>1.1.0-SNAPSHOT</version>
</parent>
<groupId>org.openecard.bindings</groupId>
<artifactId>http</artifactId>
<packaging>jar</packaging>
<name>HTTP Binding</name>
<groupId>org.openecard.bindings</groupId>
<artifactId>http</artifactId>
<packaging>jar</packaging>
<name>HTTP Binding</name>
<dependencies>
<dependency>
<groupId>org.openecard.transport</groupId>
<artifactId>http-core-shade</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.openecard</groupId>
<artifactId>addon</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.openecard.wsdef</groupId>
<artifactId>wsdef-client</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependencies>
<dependency>
<groupId>org.openecard.transport</groupId>
<artifactId>http-core-shade</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.openecard.crypto</groupId>
<artifactId>tls</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.openecard</groupId>
<artifactId>addon</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.openecard.wsdef</groupId>
<artifactId>wsdef-client</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.openecard.transport</groupId>
<artifactId>dispatcher</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.openecard.ifd</groupId>
<artifactId>ifd-core</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.openecard</groupId>
<artifactId>event-manager</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.openecard.sal</groupId>
<artifactId>tiny-sal</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.openecard.ifd.scio-backend</groupId>
<artifactId>pcsc</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.openecard.wsdef</groupId>
<artifactId>jaxb-marshaller</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.openecard</groupId>
<artifactId>management</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.openecard.gui</groupId>
<artifactId>swing</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.openecard.addons</groupId>
<artifactId>tr03112</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.openecard.addons</groupId>
<artifactId>status</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<dependency>
<groupId>org.openecard.transport</groupId>
<artifactId>dispatcher</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.openecard.ifd</groupId>
<artifactId>ifd-core</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.openecard</groupId>
<artifactId>event-manager</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.openecard.sal</groupId>
<artifactId>tiny-sal</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.openecard.ifd.scio-backend</groupId>
<artifactId>pcsc</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.openecard.wsdef</groupId>
<artifactId>jaxb-marshaller</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.openecard</groupId>
<artifactId>management</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.openecard.gui</groupId>
<artifactId>swing</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.openecard.addons</groupId>
<artifactId>tr03112</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.openecard.addons</groupId>
<artifactId>status</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<!-- generate file listing for the integrated webserver -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>process-resources</phase>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
<configuration>
<target>
<fileset id="files" dir="${basedir}/src/main/resources/www" includes="**" />
<pathconvert targetos="unix" property="files" refid="files">
<map from="${basedir}/src/main/resources" to=""/>
</pathconvert>
<echo file="${basedir}/target/classes/www-files" message="${files}" />
</target>
</configuration>
</plugin>
</plugins>
</build>
<build>
<plugins>
<!-- generate file listing for the integrated webserver -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>process-resources</phase>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
<configuration>
<target>
<fileset id="files" dir="${basedir}/src/main/resources/www" includes="**" />
<pathconvert targetos="unix" property="files" refid="files">
<map from="${basedir}/src/main/resources" to=""/>
</pathconvert>
<echo file="${basedir}/target/classes/www-files" message="${files}" />
</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
......@@ -43,8 +43,9 @@ import org.openecard.control.binding.http.interceptor.StatusLineResponseIntercep
*
* @author Moritz Horsch
* @author Dirk Petrautzki
* @author Tobias Wich
*/
public class HTTPBinding {
public class HttpBinding {
/** Uses the default port 24727 according to BSI-TR-03112 */
public static final int DEFAULT_PORT = 24727;
......@@ -52,7 +53,7 @@ public class HTTPBinding {
private final DocumentRoot documentRoot;
private List<HttpRequestInterceptor> reqInterceptors;
private List<HttpResponseInterceptor> respInterceptors;
private HTTPService service;
private HttpService service;
private AddonManager addonManager;
public void setAddonManager(AddonManager addonManager) {
......@@ -64,7 +65,7 @@ public class HTTPBinding {
* @throws IOException If the document root cannot be read
* @throws Exception
*/
public HTTPBinding() throws IOException, Exception {
public HttpBinding() throws IOException, Exception {
this(DEFAULT_PORT);
}
......@@ -75,7 +76,7 @@ public class HTTPBinding {
* @throws IOException If the document root cannot be read
* @throws Exception
*/
public HTTPBinding(int port) throws IOException, Exception {
public HttpBinding(int port) throws IOException, Exception {
this(port, "/www", "/www-files");
}
......@@ -88,7 +89,7 @@ public class HTTPBinding {
* @throws IOException If the document root cannot be read
* @throws Exception
*/
public HTTPBinding(int port, String documentRootPath, String listFile) throws IOException, Exception {
public HttpBinding(int port, String documentRootPath, String listFile) throws IOException, Exception {
this.port = port;
// Create document root
......@@ -103,7 +104,7 @@ public class HTTPBinding {
this.respInterceptors = respInterceptors;
}
public void start() throws Exception {
public void start(boolean tls) throws Exception {
// Add default interceptors if none are given
if (reqInterceptors == null) {
reqInterceptors = Collections.emptyList();
......@@ -120,7 +121,11 @@ public class HTTPBinding {
}
HttpAppPluginActionHandler handler = new HttpAppPluginActionHandler(addonManager);
service = new HTTPService(port, handler, reqInterceptors, respInterceptors);
if (! tls) {
service = new HttpService(port, handler, reqInterceptors, respInterceptors);
} else {
service = new HttpsService(port, handler, reqInterceptors, respInterceptors);
}
service.start();
}
......
......@@ -26,7 +26,7 @@ package org.openecard.control.binding.http;
/**
* @author Moritz Horsch <horsch@cdc.informatik.tu-darmstadt.de>
*/
public class HTTPException extends Exception {
public class HttpException extends Exception {
private static final long serialVersionUID = 1L;
......@@ -37,7 +37,7 @@ public class HTTPException extends Exception {
*
* @param httpStatusCode HTTPStatusCode
*/
public HTTPException(int httpStatusCode) {
public HttpException(int httpStatusCode) {
this.httpStatusCode = httpStatusCode;
}
......@@ -47,7 +47,7 @@ public class HTTPException extends Exception {
* @param httpStatusCode HTTPStatusCode
* @param message Message
*/
public HTTPException(int httpStatusCode, String message) {
public HttpException(int httpStatusCode, String message) {
super(message);
this.httpStatusCode = httpStatusCode;
}
......
/****************************************************************************
* Copyright (C) 2012 ecsec GmbH.
* Copyright (C) 2012-2015 ecsec GmbH.
* All rights reserved.
* Contact: ecsec GmbH (info@ecsec.de)
*
......@@ -25,10 +25,12 @@ package org.openecard.control.binding.http;
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.util.List;
import org.openecard.apache.http.ConnectionClosedException;
import org.openecard.apache.http.ConnectionReuseStrategy;
import org.openecard.apache.http.HttpRequestInterceptor;
import org.openecard.apache.http.HttpResponseFactory;
......@@ -39,7 +41,6 @@ import org.openecard.apache.http.impl.DefaultHttpResponseFactory;
import org.openecard.apache.http.protocol.BasicHttpContext;
import org.openecard.apache.http.protocol.HttpProcessor;
import org.openecard.apache.http.protocol.HttpRequestHandler;
import org.openecard.apache.http.protocol.HttpService;
import org.openecard.apache.http.protocol.ImmutableHttpProcessor;
import org.openecard.apache.http.protocol.UriHttpRequestHandlerMapper;
import org.slf4j.Logger;
......@@ -47,15 +48,17 @@ import org.slf4j.LoggerFactory;
/**
* @author Moritz Horsch <horsch@cdc.informatik.tu-darmstadt.de>
*
* @author Moritz Horsch
* @author Tobias Wich
*/
public class HTTPService implements Runnable {
public class HttpService implements Runnable {
private static final Logger logger = LoggerFactory.getLogger(HTTPService.class);
private static final Logger logger = LoggerFactory.getLogger(HttpService.class);
private static final int backlog = 10;
private final Thread thread;
private final ServerSocket server;
private final HttpService service;
private final org.openecard.apache.http.protocol.HttpService service;
protected final ServerSocket server;
/**
* Creates a new HTTPService.
......@@ -66,7 +69,7 @@ public class HTTPService implements Runnable {
* @param respInterceptors
* @throws Exception
*/
public HTTPService(int port, HttpRequestHandler handler, List<HttpRequestInterceptor> reqInterceptors,
public HttpService(int port, HttpRequestHandler handler, List<HttpRequestInterceptor> reqInterceptors,
List<HttpResponseInterceptor> respInterceptors) throws Exception {
thread = new Thread(this, "Open-eCard Localhost-Binding");
server = new ServerSocket(port, backlog, InetAddress.getByName("127.0.0.1"));
......@@ -85,7 +88,7 @@ public class HTTPService implements Runnable {
handlerRegistry.register("*", handler);
// create service instance
service = new HttpService(httpProcessor, connectionReuseStrategy, responseFactory, handlerRegistry);
service = new org.openecard.apache.http.protocol.HttpService(httpProcessor, connectionReuseStrategy, responseFactory, handlerRegistry);
}
/**
......@@ -106,6 +109,10 @@ public class HTTPService implements Runnable {
}
}
protected Socket accept() throws IOException, HttpServiceError {
return this.server.accept();
}
@Override
public void run() {
while (! Thread.interrupted()) {
......@@ -114,17 +121,21 @@ public class HTTPService implements Runnable {
CharsetDecoder dec = Charset.forName("UTF-8").newDecoder();
CharsetEncoder enc = Charset.forName("UTF-8").newEncoder();
connection = new DefaultBHttpServerConnection(8192, dec, enc, null);
connection.bind(this.server.accept());
connection.bind(accept());
new Thread() {
@Override
public void run() {
try {
if (connection.isOpen()) {
while (connection.isOpen()) {
service.handleRequest(connection, new BasicHttpContext());
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
} catch (ConnectionClosedException ex) {
// connection closed by client, this is the expected outcome
} catch (org.openecard.apache.http.HttpException ex) {
logger.error("Error processing HTTP request or response.", ex);
} catch (IOException ex) {
logger.error("IO Error while processing HTTP request or response.", ex);
} finally {
try {
connection.shutdown();
......@@ -134,8 +145,12 @@ public class HTTPService implements Runnable {
}
}.start();
} catch (Exception e) {
logger.error(e.getMessage(), e);
} catch (HttpsServiceError ex) {
logger.error("Failed to initialize TLS server socket.", ex);
// no chance this gets better, just close down the server
return;
} catch (IOException | HttpServiceError ex) {
logger.error(ex.getMessage(), ex);
}
}
}
......
/****************************************************************************
* Copyright (C) 2015 ecsec GmbH.
* All rights reserved.
* Contact: ecsec GmbH (info@ecsec.de)
*
* This file is part of the Open eCard App.
*
* GNU General Public License Usage
* This file may be used under the terms of the GNU General Public
* License version 3.0 as published by the Free Software Foundation
* and appearing in the file LICENSE.GPL included in the packaging of
* this file. Please review the following information to ensure the
* GNU General Public License version 3.0 requirements will be met:
* http://www.gnu.org/copyleft/gpl.html.
*
* Other Usage
* Alternatively, this file may be used in accordance with the terms
* and conditions contained in a signed written agreement between
* you and ecsec GmbH.
*
***************************************************************************/
package org.openecard.control.binding.http;
/**
* Exception indicationg a problem while initializing the HttpServer.
*
* @author Tobias Wich
*/
public class HttpServiceError extends Exception {
public HttpServiceError(String message) {
super(message);
}
public HttpServiceError(String message, Throwable cause) {
super(message, cause);
}
}
/****************************************************************************
* Copyright (C) 2015 ecsec GmbH.
* All rights reserved.
* Contact: ecsec GmbH (info@ecsec.de)
*
* This file is part of the Open eCard App.
*
* GNU General Public License Usage
* This file may be used under the terms of the GNU General Public
* License version 3.0 as published by the Free Software Foundation
* and appearing in the file LICENSE.GPL included in the packaging of
* this file. Please review the following information to ensure the
* GNU General Public License version 3.0 requirements will be met:
* http://www.gnu.org/copyleft/gpl.html.
*
* Other Usage
* Alternatively, this file may be used in accordance with the terms
* and conditions contained in a signed written agreement between
* you and ecsec GmbH.
*
***************************************************************************/
package org.openecard.control.binding.http;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.security.SecureRandom;
import java.util.List;
import org.openecard.apache.http.HttpRequestInterceptor;
import org.openecard.apache.http.HttpResponseInterceptor;
import org.openecard.apache.http.protocol.HttpRequestHandler;
import org.openecard.bouncycastle.crypto.tls.TlsServerProtocol;
import org.openecard.crypto.tls.SocketWrapper;
import org.openecard.common.util.SecureRandomFactory;
/**
*
* @author Tobias Wich
*/
public class HttpsService extends HttpService {
public HttpsService(int port, HttpRequestHandler handler, List<HttpRequestInterceptor> reqInterceptors,
List<HttpResponseInterceptor> respInterceptors) throws Exception {
super(port, handler, reqInterceptors, respInterceptors);
}
@Override
protected Socket accept() throws IOException, HttpServiceError, HttpsServiceError {
Socket plainSocket = super.accept();
LocalKeystoreTlsServer tlsServer = new LocalKeystoreTlsServer();
InputStream plainIn = plainSocket.getInputStream();
OutputStream plainOut = plainSocket.getOutputStream();
SecureRandom rand = SecureRandomFactory.create(32);
TlsServerProtocol handler = new TlsServerProtocol(plainIn, plainOut, rand);
handler.accept(tlsServer);
Socket secSocket = new SocketWrapper(plainSocket, handler.getInputStream(), handler.getOutputStream());
return secSocket;
}