/**
* OnionCoffee - Anonymous Communication through TOR Network
* Copyright (C) 2005-2007 RWTH Aachen University, Informatik IV
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
package TorJava;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.util.concurrent.ConcurrentHashMap;
import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLPeerUnverifiedException;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.TrustManager;
/**
* main class for server functionality
*
* @author Lexi Pimenidis
* @version unstable
*/
class ServerMain {
Tor tor;
Thread or_listener;
SSLServerSocket or_server;
ConcurrentHashMap<String,TLSConnection> tls_connection; // pointer to tls-connections in FirstNodeHandler!!
static String[] enabledSuites = { /*"SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA",*/
"TLS_DHE_RSA_WITH_AES_128_CBC_SHA" };
static String filenameKeyStore = "/tmp";
/**
* creates the TLS server socket and installs a dispatcher for incoming
* data.
*
* @param or_port
* the port to open for or-connections
* @param dir_port
* the port to open for directory services
* @exception IOException
* @exception SSLPeerUnverifiedException
*/
ServerMain(Tor tor, int or_port, int dir_port)
throws IOException, SSLPeerUnverifiedException, SSLException
{
this.tor = tor;
if (or_port < 1)
throw new IOException("invalid port given");
if (dir_port < 1)
throw new IOException("invalid port given");
if (or_port > 0xffff)
throw new IOException("invalid port given");
if (dir_port > 0xffff)
throw new IOException("invalid port given");
tls_connection = tor.fnh.tls;
KeyManager kms[] = new KeyManager[1];
kms[0] = tor.privateKeyHandler;
// use the keys and certs from above to connect to Tor-network
try {
TrustManager[] tms = { new TorX509TrustManager() };
SSLContext context = SSLContext.getInstance("TLS");
context.init(kms, tms, null);
SSLServerSocketFactory factory = (SSLServerSocketFactory) context
.getServerSocketFactory();
or_server = (SSLServerSocket) factory.createServerSocket(or_port);
// FIXME: check certificates received in TLS
/*
* // for debugging purposes
* javax.net.ssl.HandshakeCompletedListener hscl = new
* javax.net.ssl.HandshakeCompletedListener() { public void
* handshakeCompleted(HandshakeCompletedEvent e) { try {
* System.out.println("Cipher: "+e.getCipherSuite());
* java.security.cert.Certificate[] chain =
* e.getLocalCertificates(); System.out.println("Send cert-chain of
* length "+chain.length); for(int i=0;i<chain.length;++i)
* System.out.println(" cert "+i+": "+chain[i].toString()); chain =
* e.getPeerCertificates(); System.out.println("Recieved cert-chain
* of length "+chain.length); for(int i=0;i<chain.length;++i)
* System.out.println(" cert "+i+": "+chain[i].toString()); }
* catch(Exception ex) {} } };
* tls.addHandshakeCompletedListener(hscl);
*/
// TODO: Re-enable this
//or_server.setEnabledCipherSuites(enabledSuites);
// start listening for incoming data
or_listener = new Thread() {
public void run() {
try {
while (true) {
try {
SSLSocket ssl = (SSLSocket) (or_server.accept());
ssl.setEnabledCipherSuites(enabledSuites);
ssl.startHandshake();
TLSConnection tls = new TLSConnection(ssl);
// add connection to array
String descr = ssl.getInetAddress()
.getHostAddress()
+ ":" + ssl.getPort();
Logger.logTLS(Logger.VERBOSE,"Incoming TLS connection from " + descr);
tls_connection.put(descr, tls);
} catch (SecurityException e) {
}
}
} catch (IOException e) {
}
}
};
or_listener.start();
/*} catch (NoSuchProviderException e) {
SSLException e2 = new SSLException(e.getMessage());
e2.setStackTrace(e.getStackTrace());
throw e2;*/
} catch (NoSuchAlgorithmException e) {
SSLException e2 = new SSLException(e.getMessage());
e2.setStackTrace(e.getStackTrace());
throw e2;
} catch (KeyManagementException e) {
SSLException e2 = new SSLException(e.getMessage());
e2.setStackTrace(e.getStackTrace());
throw e2;
}
}
/**
* @param force
* set to TRUE if close anyway as fast as possible
*/
void close(boolean force) {
Logger.logTLS(Logger.VERBOSE,"ServerMain.close(): Closing TLS server");
// tls-connections are handled by FirstNodeHandler, no need to close
// form here and there
// close connections
try {
or_server.close();
} catch (IOException e) {
}
// join thread listening on server port
try {
or_listener.join();
} catch (InterruptedException e) {
}
}
}