EMMA Coverage Report (generated Sun Mar 01 22:06:14 CET 2015)
[all classes][org.h2.security]

COVERAGE SUMMARY FOR SOURCE FILE [CipherFactory.java]

nameclass, %method, %block, %line, %
CipherFactory.java100% (1/1)89%  (8/9)92%  (307/335)87%  (71/82)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class CipherFactory100% (1/1)89%  (8/9)92%  (307/335)87%  (71/82)
CipherFactory (): void 0%   (0/1)0%   (0/3)0%   (0/2)
getKeyStoreBytes (KeyStore, String): byte [] 100% (1/1)76%  (13/17)67%  (4/6)
createServerSocket (int, InetAddress): ServerSocket 100% (1/1)82%  (33/40)92%  (11/12)
getBlockCipher (String): BlockCipher 100% (1/1)86%  (24/28)86%  (6/7)
setKeystore (): void 100% (1/1)92%  (66/72)86%  (19/22)
getKeyStore (String): KeyStore 100% (1/1)92%  (49/53)82%  (9/11)
createSocket (InetAddress, int): Socket 100% (1/1)100% (38/38)100% (11/11)
disableSSL (String []): String [] 100% (1/1)100% (34/34)100% (5/5)
enableAnonymous (String [], String []): String [] 100% (1/1)100% (50/50)100% (6/6)

1/*
2 * Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0,
3 * and the EPL 1.0 (http://h2database.com/html/license.html).
4 * Initial Developer: H2 Group
5 */
6package org.h2.security;
7 
8import java.io.ByteArrayInputStream;
9import java.io.ByteArrayOutputStream;
10import java.io.IOException;
11import java.io.InputStream;
12import java.io.OutputStream;
13import java.net.InetAddress;
14import java.net.InetSocketAddress;
15import java.net.ServerSocket;
16import java.net.Socket;
17import java.security.KeyFactory;
18import java.security.KeyStore;
19import java.security.PrivateKey;
20import java.security.cert.Certificate;
21import java.security.cert.CertificateFactory;
22import java.security.spec.PKCS8EncodedKeySpec;
23import java.util.Arrays;
24import java.util.Collections;
25import java.util.HashSet;
26import java.util.Properties;
27import javax.net.ServerSocketFactory;
28import javax.net.ssl.SSLServerSocket;
29import javax.net.ssl.SSLServerSocketFactory;
30import javax.net.ssl.SSLSocket;
31import javax.net.ssl.SSLSocketFactory;
32 
33import org.h2.api.ErrorCode;
34import org.h2.engine.SysProperties;
35import org.h2.message.DbException;
36import org.h2.store.fs.FileUtils;
37import org.h2.util.IOUtils;
38import org.h2.util.StringUtils;
39 
40/**
41 * A factory to create new block cipher objects.
42 */
43public class CipherFactory {
44 
45    /**
46     * The default password to use for the .h2.keystore file
47     */
48    public static final String KEYSTORE_PASSWORD =
49            "h2pass";
50 
51    private static final String KEYSTORE =
52            "~/.h2.keystore";
53    private static final String KEYSTORE_KEY =
54            "javax.net.ssl.keyStore";
55    private static final String KEYSTORE_PASSWORD_KEY =
56            "javax.net.ssl.keyStorePassword";
57 
58    private CipherFactory() {
59        // utility class
60    }
61 
62    /**
63     * Get a new block cipher object for the given algorithm.
64     *
65     * @param algorithm the algorithm
66     * @return a new cipher object
67     */
68    public static BlockCipher getBlockCipher(String algorithm) {
69        if ("XTEA".equalsIgnoreCase(algorithm)) {
70            return new XTEA();
71        } else if ("AES".equalsIgnoreCase(algorithm)) {
72            return new AES();
73        } else if ("FOG".equalsIgnoreCase(algorithm)) {
74            return new Fog();
75        }
76        throw DbException.get(ErrorCode.UNSUPPORTED_CIPHER, algorithm);
77    }
78 
79    /**
80     * Create a secure client socket that is connected to the given address and
81     * port.
82     *
83     * @param address the address to connect to
84     * @param port the port
85     * @return the socket
86     */
87    public static Socket createSocket(InetAddress address, int port)
88            throws IOException {
89        Socket socket = null;
90        setKeystore();
91        SSLSocketFactory f = (SSLSocketFactory) SSLSocketFactory.getDefault();
92        SSLSocket secureSocket = (SSLSocket) f.createSocket();
93        secureSocket.connect(new InetSocketAddress(address, port),
94                SysProperties.SOCKET_CONNECT_TIMEOUT);
95        secureSocket.setEnabledProtocols(
96                disableSSL(secureSocket.getEnabledProtocols()));
97        if (SysProperties.ENABLE_ANONYMOUS_TLS) {
98            String[] list = enableAnonymous(
99                    secureSocket.getEnabledCipherSuites(),
100                    secureSocket.getSupportedCipherSuites());
101            secureSocket.setEnabledCipherSuites(list);
102        }
103        socket = secureSocket;
104        return socket;
105    }
106 
107/**
108     * Create a secure server socket. If a bind address is specified, the socket
109     * is only bound to this address.
110     *
111     * @param port the port to listen on
112     * @param bindAddress the address to bind to, or null to bind to all
113     *            addresses
114     * @return the server socket
115     */
116    public static ServerSocket createServerSocket(int port,
117            InetAddress bindAddress) throws IOException {
118        ServerSocket socket = null;
119        setKeystore();
120        ServerSocketFactory f = SSLServerSocketFactory.getDefault();
121        SSLServerSocket secureSocket;
122        if (bindAddress == null) {
123            secureSocket = (SSLServerSocket) f.createServerSocket(port);
124        } else {
125            secureSocket = (SSLServerSocket) f.createServerSocket(port, 0, bindAddress);
126        }
127        secureSocket.setEnabledProtocols(
128                disableSSL(secureSocket.getEnabledProtocols()));
129        if (SysProperties.ENABLE_ANONYMOUS_TLS) {
130            String[] list = enableAnonymous(
131                    secureSocket.getEnabledCipherSuites(),
132                    secureSocket.getSupportedCipherSuites());
133            secureSocket.setEnabledCipherSuites(list);
134        }
135 
136        socket = secureSocket;
137        return socket;
138    }
139 
140    private static byte[] getKeyStoreBytes(KeyStore store, String password)
141            throws IOException {
142        ByteArrayOutputStream bout = new ByteArrayOutputStream();
143        try {
144            store.store(bout, password.toCharArray());
145        } catch (Exception e) {
146            throw DbException.convertToIOException(e);
147        }
148        return bout.toByteArray();
149    }
150 
151    /**
152     * Get the keystore object using the given password.
153     *
154     * @param password the keystore password
155     * @return the keystore
156     */
157    public static KeyStore getKeyStore(String password) throws IOException {
158        try {
159            // The following source code can be re-generated
160            // if you have a keystore file.
161            // This code is (hopefully) more Java version independent
162            // than using keystores directly. See also:
163            // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4887561
164            // (1.4.2 cannot read keystore written with 1.4.1)
165            // --- generated code start ---
166 
167            KeyStore store = KeyStore.getInstance(KeyStore.getDefaultType());
168 
169            store.load(null, password.toCharArray());
170            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
171            store.load(null, password.toCharArray());
172            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(
173                    StringUtils.convertHexToBytes(
174                            "30820277020100300d06092a864886f70d010101" +
175                            "0500048202613082025d02010002818100dc0a13" +
176                            "c602b7141110eade2f051b54777b060d0f74e6a1" +
177                            "10f9cce81159f271ebc88d8e8aa1f743b505fc2e" +
178                            "7dfe38d33b8d3f64d1b363d1af4d877833897954" +
179                            "cbaec2fa384c22a415498cf306bb07ac09b76b00" +
180                            "1cd68bf77ea0a628f5101959cf2993a9c23dbee7" +
181                            "9b19305977f8715ae78d023471194cc900b231ee" +
182                            "cb0aaea98d02030100010281810099aa4ff4d0a0" +
183                            "9a5af0bd953cb10c4d08c3d98df565664ac5582e" +
184                            "494314d5c3c92dddedd5d316a32a206be4ec0846" +
185                            "16fe57be15e27cad111aa3c21fa79e32258c6ca8" +
186                            "430afc69eddd52d3b751b37da6b6860910b94653" +
187                            "192c0db1d02abcfd6ce14c01f238eec7c20bd3bb" +
188                            "750940004bacba2880349a9494d10e139ecb2355" +
189                            "d101024100ffdc3defd9c05a2d377ef6019fa62b" +
190                            "3fbd5b0020a04cc8533bca730e1f6fcf5dfceea1" +
191                            "b044fbe17d9eababfbc7d955edad6bc60f9be826" +
192                            "ad2c22ba77d19a9f65024100dc28d43fdbbc9385" +
193                            "2cc3567093157702bc16f156f709fb7db0d9eec0" +
194                            "28f41fd0edcd17224c866e66be1744141fb724a1" +
195                            "0fd741c8a96afdd9141b36d67fff6309024077b1" +
196                            "cddbde0f69604bdcfe33263fb36ddf24aa3b9922" +
197                            "327915b890f8a36648295d0139ecdf68c245652c" +
198                            "4489c6257b58744fbdd961834a4cab201801a3b1" +
199                            "e52d024100b17142e8991d1b350a0802624759d4" +
200                            "8ae2b8071a158ff91fabeb6a8f7c328e762143dc" +
201                            "726b8529f42b1fab6220d1c676fdc27ba5d44e84" +
202                            "7c72c52064afd351a902407c6e23fe35bcfcd1a6" +
203                            "62aa82a2aa725fcece311644d5b6e3894853fd4c" +
204                            "e9fe78218c957b1ff03fc9e5ef8ffeb6bd58235f" +
205                            "6a215c97d354fdace7e781e4a63e8b"));
206            PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
207            Certificate[] certs = { CertificateFactory
208                    .getInstance("X.509")
209                    .generateCertificate(
210                            new ByteArrayInputStream(
211                                    StringUtils.convertHexToBytes(
212                            "3082018b3081f502044295ce6b300d06092a8648" +
213                            "86f70d0101040500300d310b3009060355040313" +
214                            "024832301e170d3035303532363133323630335a" +
215                            "170d3337303933303036353734375a300d310b30" +
216                            "0906035504031302483230819f300d06092a8648" +
217                            "86f70d010101050003818d0030818902818100dc" +
218                            "0a13c602b7141110eade2f051b54777b060d0f74" +
219                            "e6a110f9cce81159f271ebc88d8e8aa1f743b505" +
220                            "fc2e7dfe38d33b8d3f64d1b363d1af4d87783389" +
221                            "7954cbaec2fa384c22a415498cf306bb07ac09b7" +
222                            "6b001cd68bf77ea0a628f5101959cf2993a9c23d" +
223                            "bee79b19305977f8715ae78d023471194cc900b2" +
224                            "31eecb0aaea98d0203010001300d06092a864886" +
225                            "f70d01010405000381810083f4401a279453701b" +
226                            "ef9a7681a5b8b24f153f7d18c7c892133d97bd5f" +
227                            "13736be7505290a445a7d5ceb75522403e509751" +
228                            "5cd966ded6351ff60d5193de34cd36e5cb04d380" +
229                            "398e66286f99923fd92296645fd4ada45844d194" +
230                            "dfd815e6cd57f385c117be982809028bba1116c8" +
231                            "5740b3d27a55b1a0948bf291ddba44bed337b9"))), };
232            store.setKeyEntry("h2", privateKey, password.toCharArray(), certs);
233            // --- generated code end ---
234            return store;
235        } catch (Exception e) {
236            throw DbException.convertToIOException(e);
237        }
238    }
239 
240    private static void setKeystore() throws IOException {
241        Properties p = System.getProperties();
242        if (p.getProperty(KEYSTORE_KEY) == null) {
243            String fileName = KEYSTORE;
244            byte[] data = getKeyStoreBytes(getKeyStore(
245                    KEYSTORE_PASSWORD), KEYSTORE_PASSWORD);
246            boolean needWrite = true;
247            if (FileUtils.exists(fileName) && FileUtils.size(fileName) == data.length) {
248                // don't need to overwrite the file if it did not change
249                InputStream fin = FileUtils.newInputStream(fileName);
250                byte[] now = IOUtils.readBytesAndClose(fin, 0);
251                if (now != null && Arrays.equals(data, now)) {
252                    needWrite = false;
253                }
254            }
255            if (needWrite) {
256                try {
257                    OutputStream out = FileUtils.newOutputStream(fileName, false);
258                    out.write(data);
259                    out.close();
260                } catch (Exception e) {
261                    throw DbException.convertToIOException(e);
262                }
263            }
264            String absolutePath = FileUtils.toRealPath(fileName);
265            System.setProperty(KEYSTORE_KEY, absolutePath);
266        }
267        if (p.getProperty(KEYSTORE_PASSWORD_KEY) == null) {
268            System.setProperty(KEYSTORE_PASSWORD_KEY, KEYSTORE_PASSWORD);
269        }
270    }
271 
272    private static String[] enableAnonymous(String[] enabled, String[] supported) {
273        HashSet<String> set = new HashSet<String>();
274        Collections.addAll(set, enabled);
275        for (String x : supported) {
276            if (!x.startsWith("SSL") &&
277                    x.indexOf("_anon_") >= 0 &&
278                    x.indexOf("_AES_") >= 0 &&
279                    x.indexOf("_SHA") >= 0) {
280                set.add(x);
281            }
282        }
283        return set.toArray(new String[0]);
284    }
285 
286    private static String[] disableSSL(String[] enabled) {
287        HashSet<String> set = new HashSet<String>();
288        for (String x : enabled) {
289            if (!x.startsWith("SSL")) {
290                set.add(x);
291            }
292        }
293        return set.toArray(new String[0]);
294    }
295 
296}

[all classes][org.h2.security]
EMMA 2.0.5312 (C) Vladimir Roubtsov