summaryrefslogtreecommitdiffstats
path: root/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/util/Identity.java
blob: c288fcabdba2e8c2edae51e87257ae0e4b7052a4 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
package org.openslx.bwlp.sat.util;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.sql.SQLException;

import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;

import org.apache.log4j.Logger;
import org.openslx.bwlp.sat.database.mappers.DbConfiguration;
import org.openslx.util.QuickTimer;
import org.openslx.util.QuickTimer.Task;

public class Identity {

	private static final Logger LOGGER = Logger.getLogger(Identity.class);

	private static final String ALIAS = "dozmod";

	private static final String PASSWORD = "donotchangeme";

	private static KeyStore currentKeyStore = null;

	public static KeyStore loadCertificate() {
		if (currentKeyStore != null)
			return currentKeyStore;
		KeyStore keystore = null;
		try {
			keystore = DbConfiguration.loadKeyStore(PASSWORD);
		} catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | SQLException
				| IOException e) {
			LOGGER.error("Could not load existing keystore from database", e);
			LOGGER.info("Will generate a new temporary key. Please fix the existing key"
					+ " or delete it to permanently generate a new one");
		}
		if (keystore == null) {
			if (!generateCertificate()) {
				LOGGER.error("Could not create certificate, encrypted connections not supported");
				return null;
			}
			try {
				keystore = DbConfiguration.loadKeyStore(PASSWORD);
			} catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | SQLException
					| IOException e) {
				LOGGER.error("Error loading key", e);
			}
			if (keystore == null) {
				LOGGER.error("Could not load freshly generated certificate back from db. Something's fishy.");
				return null;
			}
		}
		currentKeyStore = keystore;
		return keystore;
	}

	public static SSLContext getSSLContext() {
		if (loadCertificate() == null)
			return null;
		KeyManagerFactory kmf;
		try {
			kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
			kmf.init(currentKeyStore, PASSWORD.toCharArray());
		} catch (NoSuchAlgorithmException | UnrecoverableKeyException | KeyStoreException e) {
			LOGGER.warn("Could not create a key manager factory, SSL unavailable", e);
			return null;
		}
		SSLContext sslContext;
		try {
			sslContext = SSLContext.getInstance("TLSv1.2");
		} catch (NoSuchAlgorithmException e) {
			LOGGER.warn("Could not create a TLS1.2 context, SSL unavailable", e);
			return null;
		}
		KeyManager[] keyManagers = kmf.getKeyManagers();
		try {
			sslContext.init(keyManagers, null, null);
		} catch (KeyManagementException e) {
			LOGGER.warn("Could not find a suitable cert/key in the keystore. SSL unavailable", e);
		}
		return sslContext;
	}

	private static boolean generateCertificate() {
		File tmpFile = null;
		try {
			tmpFile = File.createTempFile("certfile", ".jks");
			tmpFile.delete();
		} catch (IOException e1) {
			LOGGER.error("Could not generate temp file for self-signed cert container", e1);
			return false;
		}
		try {
			LOGGER.info("Generating certificate for this server...");
			final Process proc;
			try {
				proc = Runtime.getRuntime().exec(
						new String[] { "keytool", "-genkeypair", "-alias", ALIAS, "-keyalg", "rsa",
								"-validity", "3000", "-keypass", PASSWORD, "-storepass", PASSWORD,
								"-keystore", tmpFile.getAbsolutePath(), "-storetype", "JKS", "-dname",
								"CN=dozmodserver" });
				QuickTimer.scheduleOnce(new Task() {
					@Override
					public void fire() {
						try {
							proc.exitValue();
							proc.destroy();
						} catch (IllegalThreadStateException e) {
						}
					}
				}, 10000);
			} catch (IOException e) {
				LOGGER.error("Launching keytool failed", e);
				return false;
			}
			int exitCode;
			try {
				exitCode = proc.waitFor();
			} catch (InterruptedException e) {
				LOGGER.warn("Got interrupted while creating the certificate");
				proc.destroy();
				return false;
			}
			if (exitCode != 0) {
				LOGGER.warn("keytool returned exit code " + exitCode);
				InputStream is = proc.getInputStream();
				BufferedReader br = new BufferedReader(new InputStreamReader(is));
				try {
					String line;
					while (null != (line = br.readLine())) {
						LOGGER.info(line);
					}
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				return false;
			}
			LOGGER.info("Certificate successfully created!");
			try {
				DbConfiguration.saveKeyStore(tmpFile);
			} catch (SQLException | IOException e) {
				LOGGER.error("Could not import generated keystore to database", e);
				return false;
			}
			return true;
		} finally {
			tmpFile.delete();
		}
	}

}