X509TrustManagerWrapper.java

package fr.umlv.ji.ssl;
import java.io.*;
import javax.net.ssl.*;
import java.security.*;
import java.security.cert.*;
import javax.security.auth.callback.*;

public class X509TrustManagerWrapper implements X509TrustManager {
  // Objet de stockage des clefs associé
  protected KeyStore ks;
  // Nom du fichier de stockage des certificats de confiance
  protected String trustStore;
  // Mot de passe de protection du fichier de stockage
  protected char[] trustSecret;
  // Gestionnaire encapsulé
  protected X509TrustManager tm;
  // Gestionnaire d'interaction avec l'utilisateur
  // (voir chapitre sur la sécurité)
  protected CallbackHandler handler;
  
  /** Construteur du gestionnaire de certificats de confiance.  */
  public X509TrustManagerWrapper(String trustStore,
                 char[] trustSecret,
                 X509TrustManager tm,
                 CallbackHandler handler)
    throws IOException, GeneralSecurityException {
    ks = SSLHelper.getKeyStore(trustStore,trustSecret);
    this.tm = tm;
    this.trustStore = trustStore;
    this.trustSecret = trustSecret;
    this.handler = handler;
  }
  public void checkClientTrusted(X509Certificate[] chain,
                 String authType)
    throws CertificateException {
    try {
      // Vérifie si le certificat fait partie des certificats acceptés
      try {
    if(ks.getCertificateAlias(chain[0])!=null) return;
      } catch (KeyStoreException e) {}
      // Teste si le certificat est déjà accepté par défaut
      tm.checkClientTrusted(chain, authType);
    } catch (CertificateException ce) {
      // Interaction avec l'utilisateur en cas d'erreur
      addCertificateCallback(chain, ce);
    }
  }
  public void checkServerTrusted(X509Certificate[] chain,
                 String authType)
    throws CertificateException {
    try {
      // Vérifie si le certificat fait partie des certificats acceptés
      try {
    if(ks.getCertificateAlias(chain[0])!= null) return;
      } catch (KeyStoreException e) {}
      // Teste si le certificat est déjà accepté par défaut
      tm.checkServerTrusted(chain, authType);
    } catch (CertificateException ce) {
      // Interaction avec l'utilisateur en cas d'erreur
      addCertificateCallback(chain, ce);
    }
  }
  public X509Certificate[] getAcceptedIssuers() {
    return tm.getAcceptedIssuers();    // Appel par défaut
  }
  
  /**
   * Méthode interagissant avec l'utilisateur pour ajouter éventuellement
   * un nouveau certificat dans le fichier de stockage des certificats de
   * confiance.
   */
  private void addCertificateCallback(X509Certificate[] chain,
                      CertificateException ce)
    throws CertificateException {
    try {
      // Construction d'un objet pour l'interaction avec l'utilisateur
      // (voir chapitre sur la sécurité)
      ConfirmationCallback cc =
    new ConfirmationCallback("Trust:\n"+chain[0].toString(),
                 ConfirmationCallback.WARNING,
                 ConfirmationCallback.YES_NO_OPTION,
                 ConfirmationCallback.NO);
      // Interaction avec l'utilisateur
      // (voir chapitre sur la sécurité)
      handler.handle(new Callback[]{cc});
      // Si le certificat n'est pas accepté lever l'exception 
      if (cc.getSelectedIndex() == ConfirmationCallback.NO)
    throw ce;
      // Demande de sauvegarde
      cc = new ConfirmationCallback("Save certificate ?",
                    ConfirmationCallback.WARNING,
                    ConfirmationCallback.YES_NO_OPTION,
                    ConfirmationCallback.NO);
      handler.handle(new Callback[]{cc});
      // Si le certificat ne doit pas être sauvé
      if (cc.getSelectedIndex() == ConfirmationCallback.NO)
    return;
      // Ajouter le certificat aux certificats acceptés
      int size = ks.size();
      ks.setCertificateEntry("alias" + (size+1), chain[0]);
      // Mise à jour du fichier de stockage des clefs
      FileOutputStream out = new FileOutputStream(trustStore);
      ks.store(out, trustSecret);
      out.close();
    } catch(Exception ie) { throw ce; } 
  }
}