summaryrefslogblamecommitdiffstats
path: root/dozentenmodul/src/main/java/org/openslx/dozmod/gui/GraphicalCertHandler.java
blob: 99c03373e9bd924a7bc93b31edcf2c102417dbb2 (plain) (tree)































                                                                                                                      










                                                                                                                                                      












                                                                                                                




                                                                                                          

                                                          

                                                                                                     
                                       



                                                                                           






                                                                                                                                    
                                                          
                                                                                                              












                                                                                                                           
                                                                                                    







































                                                                                                                              
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) {
				Boolean ret = Gui.syncExec(new GuiCallable<Boolean>() {
					@Override
					public Boolean run() {
						return Gui.showMessageBox(null,
								"Der Satellit besitzt kein Zertifikat. Verschlüsselte Verbindung nicht möglich.\n\n"
										+ "Möchten Sie trotzdem fortfahren?", MessageType.WARNING, LOGGER,
								null);
					}
				});
				if (ret)
					return;
				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 finger print
			byte[] expectedFingerprint = FingerprintManager.getKnownFingerprint(address);
			if (expectedFingerprint == null) {
				expectedFingerprint = FingerprintManager.getSuggestedFingerprint(address);
			}
			final String question;
			if (expectedFingerprint == null) {
				// First time we connect to this server, so remember the finger print
				FingerprintManager.saveKnownFingerprint(address, actualFingerprint);
				return;
			} else if (Arrays.equals(actualFingerprint, expectedFingerprint)) {
				// Known, matches, everything's fine
				return;
			} else {
				byte[] sf = FingerprintManager.getSuggestedFingerprint(address);
				if (sf != null && Arrays.equals(actualFingerprint, sf)) {
					// User stored invalid finger print, but master suggests the finger print we found.
					// It probably changed, the satellite told the master server, but the user doesn't know yet.
					FingerprintManager.saveKnownFingerprint(address, actualFingerprint);
					return;
				}
				// Known, mismatch, panic!
				question = "!!! ALARM !!!! ALARM !!!\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.saveKnownFingerprint(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;
	}

}