This topic applies to Java version only
With the default settings db4o client-server communication is not encrypted and thus can potentially be a dangerous security hole. This can be fixed with a new pluggable socket client/server implementation. Let's look at a simple example - we will use SSL protocol to protect our communication channel.
Basically the task is to create a NativeSocketFactory implementation that will create sockets able to communicate through an encrypted channel. In Java these would be SSLServerSocket and SSLSocket.
01/* Copyright (C) 2007 db4objects Inc. http://www.db4o.com */ 02
package com.db4odoc.ssl; 03
04
import java.io.IOException; 05
import java.net.ServerSocket; 06
import java.net.Socket; 07
08
import javax.net.ssl.SSLContext; 09
10
import com.db4o.config.NativeSocketFactory; 11
12
public class SecureSocketFactory implements NativeSocketFactory { 13
14
private SSLContext _context; 15
16
public SecureSocketFactory(SSLContext context) { 17
_context = context; 18
} 19
20
public ServerSocket createServerSocket(int port) throws IOException { 21
System.out.println("SERVER on " + port); 22
return _context.getServerSocketFactory().createServerSocket(port); 23
} 24
25
public Socket createSocket(String hostName, int port) throws IOException { 26
System.out.println("CLIENT on " + port); 27
return _context.getSocketFactory().createSocket(hostName, port); 28
} 29
30
public Object deepClone(Object context) { 31
return this; 32
} 33
34
}
In order for this class to work correctly we need to provide a correctly initialized SSLContext. For those who are not familiar with Java SSL implementation it is recommended to get acquainted with Java documentation for SSLContext, TrustManager, KeyStore and KeyManagerFactory APIs.
For encryption purposes we will need to create a new keystore. This can be done with the following command:
keytool -genkey -keystore SSLcert -storepass password
This command creates a file SSLcert, which contains a keystore protected by "password" password. For a test keystore you can provide any answers to the keytool questions and leave the key password the same as the keystore password. For easy access copy the SSLcert file into your projects directory.
Now we are ready to create a SecureSocketFactory
01private static SecureSocketFactory createSecureSocketFactory() throws Exception{ 02
SSLContext sc; 03
04
//Create a trust manager that does not validate certificate chains 05
TrustManager[] trustAllCerts = createTrustManager(); 06
07
// Install the all-trusting trust manager 08
sc = SSLContext.getInstance("SSLv3"); 09
KeyStore ks = KeyStore.getInstance(KEYSTORE_ID); 10
ks.load(new FileInputStream(KEYSTORE_PATH), null); 11
KeyManagerFactory kmf = KeyManagerFactory.getInstance( KeyManagerFactory.getDefaultAlgorithm() ); 12
kmf.init( ks, KEYSTORE_PASSWORD.toCharArray()); 13
14
sc.init(kmf.getKeyManagers(), trustAllCerts, new java.security.SecureRandom()); 15
return new SecureSocketFactory(sc); 16
}
01private static TrustManager[] createTrustManager(){ 02
return new TrustManager[]{ 03
new X509TrustManager() { 04
public java.security.cert.X509Certificate[] getAcceptedIssuers() { 05
return null; 06
} 07
public void checkClientTrusted( 08
java.security.cert.X509Certificate[] certs, String authType) { 09
} 10
public void checkServerTrusted( 11
java.security.cert.X509Certificate[] certs, String authType) { 12
} 13
} 14
}; 15
}
Starting a server and opening client connections with the new socket factory is as simple as usual:
01public static void main(String[] args) throws Exception { 02
03
// Create a SecureSocketFactory for the SSL context 04
socketFactory = createSecureSocketFactory(); 05
06
Configuration config = Db4o.newConfiguration(); 07
ObjectServer db4oServer = Db4o.openServer(config, FILE, PORT, 08
socketFactory); 09
db4oServer.grantAccess(USER, PASSWORD); 10
try { 11
storeObjectsRemotely(HOST, PORT, USER, PASSWORD); 12
queryRemoteServer(HOST, PORT, USER, PASSWORD); 13
} finally { 14
db4oServer.close(); 15
} 16
}
1private static void storeObjectsRemotely(String host, int port,String user,String password) throws IOException { 2
Configuration config = Db4o.newConfiguration(); 3
ObjectContainer client=Db4o.openClient(config, "localhost",port,user,password, socketFactory); 4
Pilot pilot = new Pilot("Fernando Alonso", 89); 5
client.set(pilot); 6
client.close(); 7
}
1private static void queryRemoteServer(String host, int port,String user,String password) throws IOException { 2
Configuration config = Db4o.newConfiguration(); 3
ObjectContainer client=Db4o.openClient(config, "localhost",port,user,password, socketFactory); 4
listResult(client.get(new Pilot(null, 0))); 5
client.close(); 6
}