summaryrefslogblamecommitdiffstats
path: root/dozentenmodul/src/main/java/org/openslx/dozmod/gui/GraphicalCertHandler.java
blob: 48b6a14abec4c8c5af312efee5b50b9da8a757c1 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14













                                               

                                           

                                                            
                                          



                                                 
                                                                                                              









                                                                                                                      



                                                                                       

                                                                                                                                         



                                               












                                                                                                                




                                                                                                          

                                                          

                                                                                                     
                                       



                                                                                           






                                                                                                                                    
                                                          

                                                                                                                               








                                                                                                                          
                                                                                                    




















                                                                                   

                                                                                                                           




                                                                                                   


                                                                                                                                      











                                                                    
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.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import org.openslx.dozmod.authentication.FingerprintManager;
import org.openslx.dozmod.gui.Gui.GuiCallable;
import org.openslx.dozmod.gui.helper.I18n;
import org.openslx.dozmod.gui.helper.MessageType;

public class GraphicalCertHandler {

	private static final Logger LOGGER = LogManager.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,
								I18n.GUI.getString("GraphicalCertHandler.Message.warning.noCertificate"),
								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 = I18n.GUI.getString("GraphicalCertHandler.Message.yesNo.fingerprintChanged", address,
						new BigInteger(expectedFingerprint).toString(16), actualFingerprintReadable);
			}
			// 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(I18n.GUI.getString("GraphicalCertHandler.Message.error.couldNotGetSSLContext"),
					MessageType.ERROR, LOGGER, e);
		}
		if (ctx != null) {
			try {
				ctx.init(null, new TrustManager[] { new GuiTrustManager() }, null);
			} catch (KeyManagementException e) {
				Gui.asyncMessageBox(
						I18n.GUI.getString("GraphicalCertHandler.Message.error.couldNotInitializeSSLContext"),
						MessageType.ERROR, LOGGER, e);
				ctx = null;
			}
		}
		this.sslContext = ctx;
		this.address = address;
	}

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

}