From 9597430cdbdd5f613b3442347cbe666b1336a454 Mon Sep 17 00:00:00 2001 From: Arne Schwabe Date: Thu, 11 Jul 2013 23:38:59 +0200 Subject: Usage reflection to use Android Bouncycastle to print Subject DN, also display CN in the basic settings screen --HG-- extra : rebase_source : 6cff9134e9f0bd0e5261edd7ac0b4139b1580d3b --- src/de/blinkt/openvpn/VpnProfile.java | 6 ---- src/de/blinkt/openvpn/core/X509Utils.java | 42 ++++++++++++++++++++-- .../blinkt/openvpn/fragments/Settings_Basic.java | 41 +++++++++++++++++++-- 3 files changed, 78 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/de/blinkt/openvpn/VpnProfile.java b/src/de/blinkt/openvpn/VpnProfile.java index 190cdf9a..e44847b6 100644 --- a/src/de/blinkt/openvpn/VpnProfile.java +++ b/src/de/blinkt/openvpn/VpnProfile.java @@ -573,12 +573,6 @@ public class VpnProfile implements Serializable{ if(cachain.length <= 1 && !nonNull(mCaFilename)) OpenVPN.logMessage(0, "", context.getString(R.string.keychain_nocacert)); - for(X509Certificate cert:cachain) { - OpenVPN.logInfo(R.string.cert_from_keystore,X509Utils.getCertificateFriendlyName(cert)); - } - - - if(nonNull(mCaFilename)) { try { diff --git a/src/de/blinkt/openvpn/core/X509Utils.java b/src/de/blinkt/openvpn/core/X509Utils.java index 4d2e6668..efdda3ca 100644 --- a/src/de/blinkt/openvpn/core/X509Utils.java +++ b/src/de/blinkt/openvpn/core/X509Utils.java @@ -8,12 +8,16 @@ import de.blinkt.openvpn.VpnProfile; import org.spongycastle.util.io.pem.PemObject; import org.spongycastle.util.io.pem.PemReader; + import javax.security.auth.x500.X500Principal; import java.io.*; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; +import java.util.Hashtable; public class X509Utils { public static Certificate getCertificateFromFile(String certfilename) throws FileNotFoundException, CertificateException { @@ -70,10 +74,42 @@ public class X509Utils { } public static String getCertificateFriendlyName(X509Certificate cert) { - X500Principal principal = (X500Principal) cert.getSubjectDN(); + X500Principal principal = cert.getSubjectX500Principal(); + byte[] encodedSubject = principal.getEncoded(); + String friendlyName=null; + + /* Hack so we do not have to ship a whole Spongy/bouncycastle */ + try { + Class X509NameClass = Class.forName("com.android.org.bouncycastle.asn1.x509.X509Name"); + Method getInstance = X509NameClass.getMethod("getInstance",Object.class); + + Hashtable defaultSymbols = (Hashtable) X509NameClass.getField("DefaultSymbols").get(X509NameClass); + + if (!defaultSymbols.containsKey("1.2.840.113549.1.9.1")) + defaultSymbols.put("1.2.840.113549.1.9.1","eMail"); + + Object subjectName = getInstance.invoke(X509NameClass, encodedSubject); + + Method toString = X509NameClass.getMethod("toString",boolean.class,Hashtable.class); + + friendlyName= (String) toString.invoke(subjectName,true,defaultSymbols); + + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } catch (InvocationTargetException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } catch (NoSuchFieldException e) { + e.printStackTrace(); + } + + /* Fallback if the reflection method did not work */ + if(friendlyName==null) + friendlyName = principal.getName(); - String friendlyName = principal.getName(); - System.out.println(friendlyName); // Really evil hack to decode email address // See: http://code.google.com/p/android/issues/detail?id=21531 diff --git a/src/de/blinkt/openvpn/fragments/Settings_Basic.java b/src/de/blinkt/openvpn/fragments/Settings_Basic.java index 77025dbd..5dc4e437 100644 --- a/src/de/blinkt/openvpn/fragments/Settings_Basic.java +++ b/src/de/blinkt/openvpn/fragments/Settings_Basic.java @@ -29,6 +29,10 @@ import de.blinkt.openvpn.R; import de.blinkt.openvpn.VpnProfile; import de.blinkt.openvpn.R.id; import de.blinkt.openvpn.core.ProfileManager; +import de.blinkt.openvpn.core.X509Utils; + +import java.io.IOException; +import java.security.cert.X509Certificate; public class Settings_Basic extends Fragment implements View.OnClickListener, OnItemSelectedListener, Callback { private static final int CHOOSE_FILE_OFFSET = 1000; @@ -42,6 +46,7 @@ public class Settings_Basic extends Fragment implements View.OnClickListener, On private FileSelectLayout mCaCert; private FileSelectLayout mClientKey; private TextView mAliasName; + private TextView mAliasCertificate; private CheckBox mUseLzo; private ToggleButton mTcpUdp; private Spinner mType; @@ -58,13 +63,13 @@ public class Settings_Basic extends Fragment implements View.OnClickListener, On private SparseArray fileselects = new SparseArray(); - private void addFileSelectLayout (FileSelectLayout fsl) { + + private void addFileSelectLayout (FileSelectLayout fsl) { int i = fileselects.size() + CHOOSE_FILE_OFFSET; fileselects.put(i, fsl); fsl.setFragment(this,i); } - public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); String profileuuid =getArguments().getString(getActivity().getPackageName() + ".profileUUID"); @@ -72,6 +77,34 @@ public class Settings_Basic extends Fragment implements View.OnClickListener, On getActivity().setTitle(getString(R.string.edit_profile_title, mProfile.getName())); } + + private void setKeystoreCertficate() + { + new Thread() { + public void run() { + String certstr; + try { + + + X509Certificate cert = KeyChain.getCertificateChain(getActivity(), mProfile.mAlias)[0]; + certstr=X509Utils.getCertificateFriendlyName(cert); + } catch (Exception e) { + certstr="Could not get certificate from Keystore"; + } + + final String certStringCopy=certstr; + getActivity().runOnUiThread(new Runnable() { + + @Override + public void run() { + mAliasCertificate.setText(certStringCopy); + } + }); + + } + }.start(); + } + @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { @@ -90,6 +123,7 @@ public class Settings_Basic extends Fragment implements View.OnClickListener, On mType = (Spinner) mView.findViewById(R.id.type); mPKCS12Password = (TextView) mView.findViewById(R.id.pkcs12password); mAliasName = (TextView) mView.findViewById(R.id.aliasname); + mAliasCertificate = (TextView) mView.findViewById(id.alias_certificate); mUserName = (EditText) mView.findViewById(R.id.auth_username); mPassword = (EditText) mView.findViewById(R.id.auth_password); @@ -252,8 +286,11 @@ public class Settings_Basic extends Fragment implements View.OnClickListener, On private void setAlias() { if(mProfile.mAlias == null) { mAliasName.setText(R.string.client_no_certificate); + mAliasCertificate.setText(""); } else { + mAliasCertificate.setText("Loading certificate from Keystore..."); mAliasName.setText(mProfile.mAlias); + setKeystoreCertficate(); } } -- cgit v1.2.3