Android Open Source - mailinglistmoderator S S L Cert Dialog Preference






From Project

Back to project page mailinglistmoderator.

License

The source code is released under:

Copyright (c) 2010, Magnus Hagander All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:...

If you think the Android project mailinglistmoderator listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*
 * SSLCertDialogPreference.java - This class holds a dialog preference for polling SSL certs
 * /*from  w w w .ja  v a 2  s .c  o m*/
 * Copyright (C) 2010 Magnus Hagander <magnus@hagander.net>
 * 
 * This software is released under the BSD license.
 */
package net.hagander.mailinglistmoderator.preferences;

import java.io.IOException;
import java.math.BigInteger;
import java.net.URL;
import java.net.URLConnection;
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.ArrayList;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.X509TrustManager;

import net.hagander.mailinglistmoderator.R;

import android.content.Context;
import android.content.SharedPreferences;
import android.preference.DialogPreference;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;

public class SSLCertDialogPreference extends DialogPreference implements OnClickListener {
  private class StringTuple {
    String description;
    String value;
    public StringTuple(String description, String value) {
      this.description = description;
      this.value = value;
    }
  }

  private String sslCertError = null;
  private String sslCertFingerprint = null;
  private ArrayList<StringTuple> sslCertDetails = null;

  private EditText fingerprintField;
  private ProgressBar progressSpinner;
  private TableLayout certDetailsTableLayout;
  private TextView certErrorText;
  private Button copyButton;

  public SSLCertDialogPreference(Context context) {
    super(context, null);

      setDialogLayoutResource(R.layout.sslcertdialogprefview);
  }

  @Override
  protected void onBindDialogView(final View view) {
    fingerprintField = (EditText) view.findViewById(R.id.editCertFingerprint);
    progressSpinner = (ProgressBar) view.findViewById(R.id.progressBar1);
    certErrorText = (TextView) view.findViewById(R.id.textViewCertError);
    certDetailsTableLayout = (TableLayout) view.findViewById(R.id.tableLayoutCertDetails);
    copyButton = (Button) view.findViewById(R.id.buttonGetFromServer);
    copyButton.setOnClickListener(this);
    ((Button) view.findViewById(R.id.buttonClear)).setOnClickListener(this);


      SharedPreferences pref = getSharedPreferences();
      fingerprintField.setText(pref.getString(getKey(), ""));

      super.onBindDialogView(view);

      new Thread(new Runnable() {
      public void run() {
        FetchSSLCertDescription();
        view.post(new Runnable() {
          public void run() {
            progressSpinner.setVisibility(View.GONE);
            if (sslCertError != null) {
              certErrorText.setText(sslCertError);
              certErrorText.setVisibility(View.VISIBLE);
              return;
            }
            for (StringTuple r : sslCertDetails) {
              TableRow tr = new TableRow(certDetailsTableLayout.getContext());
              tr.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
              TextView tv_d = new TextView(certDetailsTableLayout.getContext());
              tv_d.setText(r.description + ":");
              TextView tv_v = new TextView(certDetailsTableLayout.getContext());
              tv_v.setText(r.value);
              tr.addView(tv_d);
              tr.addView(tv_v);
              certDetailsTableLayout.addView(tr, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
            }
            if (sslCertFingerprint != null) {
              copyButton.setEnabled(true);
            }
          }
        });
      }
      }).start();
  }

  @Override
  protected void onDialogClosed(boolean positiveResult) {
      if(!positiveResult)
          return;

      SharedPreferences.Editor editor = getEditor();
      editor.putString(getKey(), fingerprintField.getText().toString());
      editor.commit();
      setSummary(fingerprintField.getText());
  }

  public void onClick(View view) {
    String btn = ((Button)view).getText().toString();
    if (btn.equals("Copy from info below")) {
      if (sslCertFingerprint != null)
        fingerprintField.setText(sslCertFingerprint);
    }
    else if (btn.equals("Clear")) {
      fingerprintField.setText("");
    }
  }

  private void FetchSSLCertDescription() {
    /*
     * Fetch the description and the fingerprint for the currently configured
     * BASE URL.
     */

    /* 
     * We need to read the other preference, by stripping it out from our own key.
     * Do that by removing the " 
     */
      SharedPreferences pref = getSharedPreferences();
      String baseurl = pref.getString(getKey().replace("_whitelistedcert", "_baseurl"), "FAIL");
      if (baseurl.equals("")) {
        sslCertError = "Base URL must be set before this preference can be fetched.";
        return;
      }

      URLConnection c;
      try {
        final URL u = new URL(baseurl);
        c = u.openConnection();
      }
      catch (Exception e) {
        sslCertError = "Failed to parse or open URL!";
        return;
      }

    SSLContext context;
    try {
      context = SSLContext.getInstance("TLS");
    } catch (NoSuchAlgorithmException e) {
      sslCertError =  "Could not find TLS context!";
      return;
    }
    HttpsURLConnection sslconn  = (HttpsURLConnection) c;
    try {
      context.init(null,
          new X509TrustManager[] { new X509TrustManager() {
            public void checkClientTrusted(
                X509Certificate[] chain, String authType)
                throws CertificateException {
            }

            public void checkServerTrusted(
                X509Certificate[] chain, String authType)
                throws CertificateException {
              MessageDigest md;
              try {
                md = MessageDigest.getInstance("SHA-1");
              } catch (NoSuchAlgorithmException e) {
                sslCertError = "Could not find SHA-1 digest";
                throw new CertificateException();
              }
              md.update(chain[0].getEncoded());
              byte[] digest = md.digest();
              BigInteger bi = new BigInteger(1, digest);
                String fingerprint = String.format("%0" + (digest.length << 1) + "X", bi);

                ArrayList<StringTuple> r = new ArrayList<StringTuple>();
                r.add(new StringTuple("Subject", chain[0].getSubjectDN().toString()));
                r.add(new StringTuple("Valid from", chain[0].getNotBefore().toLocaleString()));
                r.add(new StringTuple("Valid to", chain[0].getNotAfter().toLocaleString()));
                r.add(new StringTuple("Fingerprint", fingerprint));
                r.add(new StringTuple("Chain length", String.format("%d",chain.length)));

                sslCertDetails = r;
              sslCertFingerprint = fingerprint;
            }

            public X509Certificate[] getAcceptedIssuers() {
              return new X509Certificate[0];
            }
          } }, null);
    } catch (KeyManagementException e) {
      sslCertError = String.format("Unable to set up key management: %s", e.toString());
      return;
    }
    sslconn.setSSLSocketFactory(context.getSocketFactory());

    /*
     * We must also turn off hostname verification so we don't get an exception
     * when connecting.
     */
    sslconn.setHostnameVerifier(new HostnameVerifier() {
      public boolean verify(String hostname, SSLSession session) {
        return true;
      }
    });

    try {
      sslconn.connect(); /* This should trigger our callback */
      sslconn.disconnect();
    }
    catch (IOException e) {
      sslCertError = String.format("Unable to connect to server: %s", e.toString());
    }
  }
}




Java Source Code List

net.hagander.mailinglistmoderator.MailinglistModerator.java
net.hagander.mailinglistmoderator.MessageViewActivity.java
net.hagander.mailinglistmoderator.QueueListActivity.java
net.hagander.mailinglistmoderator.ServerEditor.java
net.hagander.mailinglistmoderator.backend.ListServer.java
net.hagander.mailinglistmoderator.backend.MailMessage.java
net.hagander.mailinglistmoderator.backend.providers.Dummy.java
net.hagander.mailinglistmoderator.backend.providers.Mailman.java
net.hagander.mailinglistmoderator.backend.providers.Majordomo2.java
net.hagander.mailinglistmoderator.backend.providers.Unconfigured.java
net.hagander.mailinglistmoderator.glue.ListServerAdapter.java
net.hagander.mailinglistmoderator.glue.MailMessageAdapter.java
net.hagander.mailinglistmoderator.preferences.SSLCertDialogPreference.java