summaryrefslogtreecommitdiffstats
path: root/dozentenmodul/src/main/java/org/openslx/dozmod/gui/GraphicalCertHandler.java
blob: 07b441758243d16f0442e25d1136e3b85c4ce10a (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
package org.openslx.dozmod.gui;

import java.math.BigInteger;
import java.security.KeyManagementException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Arrays;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.log4j.Logger;
import org.openslx.dozmod.authentication.FingerprintManager;
import org.openslx.dozmod.gui.Gui.GuiCallable;
import org.openslx.dozmod.gui.helper.MessageType;

public class GraphicalCertHandler {

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

	private class GuiTrustManager implements X509TrustManager {

		@Override
		public void checkClientTrusted(X509Certificate[] certs, String authType) throws CertificateException {
		}

		@Override
		public void checkServerTrusted(X509Certificate[] certs, String authType) throws CertificateException {
			if (certs == null || certs.length == 0) {
				Gui.asyncMessageBox(
						"Der Satellit besitzt kein Zertifikat. Verschlüsselte Verbindung nicht möglich.\n\n"
								+ "Möchten Sie trotzdem fortfahren?", MessageType.WARNING, LOGGER, null);
				// TODO: Ask and do
				throw new CertificateException("No certificate provided by server");
			}
			byte[] encoded = certs[0].getEncoded();
			MessageDigest md;
			try {
				md = MessageDigest.getInstance("SHA-256");
			} catch (NoSuchAlgorithmException e) {
				LOGGER.warn("Could not get SHA-256 hash of certificate", e);
				throw new CertificateException("Could not get SHA-256 hash of certificate");
			}
			md.update(encoded);
			byte[] actualFingerprint = md.digest();
			final String actualFingerprintReadable = new BigInteger(actualFingerprint).toString(16);
			// Now check the fingerprint
			byte[] expectedFingerprint = FingerprintManager.getFingerprint(address);
			final String question;
			if (expectedFingerprint == null) {
				// Not known yet, ask
				question = "Magst du die Zahl " + actualFingerprintReadable + "?";
			} else if (Arrays.equals(actualFingerprint, expectedFingerprint)) {
				// Known, matches, everything's fine
				return;
			} else {
				// Known, mismatch, panic!
				question = "!!! ALARM !!!! ALARM !!! *trage hol*\n\n" + "Der Fingerabdruck von " + address
						+ " hat sich verändert.\n" + "Erwartet: "
						+ new BigInteger(expectedFingerprint).toString(16) + "\n" + "Vorgefunden: "
						+ actualFingerprintReadable + "\n\n"
						+ "Möchten Sie trotzdem zu diesem Satelliten verbinden?";
			}
			// Some question needs to be asked
			Boolean userOk = Gui.syncExec(new GuiCallable<Boolean>() {
				@Override
				public Boolean run() {
					return Gui.showMessageBox(null, question, MessageType.QUESTION_YESNO, null, null);
				}
			});
			if (userOk) {
				FingerprintManager.saveFingerprint(address, actualFingerprint);
			} else {
				throw new CertificateException("Rejected by user");
			}
		}

		@Override
		public X509Certificate[] getAcceptedIssuers() {
			return null;
		}

	}

	private final String address;

	private final SSLContext sslContext;

	private GraphicalCertHandler(String address) {
		SSLContext ctx = null;
		try {
			ctx = SSLContext.getInstance("TLSv1.2");
		} catch (NoSuchAlgorithmException e) {
			Gui.asyncMessageBox("Could not get TLSv1.2 SSL context", MessageType.ERROR, LOGGER, e);
		}
		if (ctx != null) {
			try {
				ctx.init(null, new TrustManager[] { new GuiTrustManager() }, null);
			} catch (KeyManagementException e) {
				Gui.asyncMessageBox("Could not initialize TLSv1.2 SSL context", MessageType.ERROR, LOGGER, e);
				ctx = null;
			}
		}
		this.sslContext = ctx;
		this.address = address;
	}

	public static SSLContext getSslContext(String address) {
		return new GraphicalCertHandler(address).sslContext;
	}

}