summaryrefslogblamecommitdiffstats
path: root/dozentenmodul/src/main/java/org/openslx/dozmod/gui/GraphicalCertHandler.java
blob: 648a04035326d8a4e3a8a0a0bf06773fcb4c0ca4 (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 {
			try {
				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");
				}
			} catch (Throwable t) {
				LOGGER.warn("Exception when checking cert of satellite", t);
				throw t;
			}
		}

		@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;
	}

}