summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArne Schwabe <arne@rfc2549.org>2013-07-12 00:01:22 +0200
committerArne Schwabe <arne@rfc2549.org>2013-07-12 00:01:22 +0200
commite1359d383c16daf5440210b07d686aac5f0a2678 (patch)
tree0d44555f457466e2a3739a94e729ed8a6e884316
parent9597430cdbdd5f613b3442347cbe666b1336a454 (diff)
Fix keychain certificate handling
Also reformat file --HG-- extra : rebase_source : cfae5aa4f9ec48c84262cc7829d2e38862fb68dc
-rw-r--r--src/de/blinkt/openvpn/VpnProfile.java1506
1 files changed, 746 insertions, 760 deletions
diff --git a/src/de/blinkt/openvpn/VpnProfile.java b/src/de/blinkt/openvpn/VpnProfile.java
index e44847b6..8f8f3c24 100644
--- a/src/de/blinkt/openvpn/VpnProfile.java
+++ b/src/de/blinkt/openvpn/VpnProfile.java
@@ -36,825 +36,811 @@ import java.util.Locale;
import java.util.UUID;
import java.util.Vector;
-public class VpnProfile implements Serializable{
- // Note that this class cannot be moved to core where it belongs since
- // the profile loading depends on it being here
- // The Serializable documentation mentions that class name change are possible
- // but the how is unclear
- //
-
- private static final long serialVersionUID = 7085688938959334563L;
- public static final int TYPE_CERTIFICATES=0;
- public static final int TYPE_PKCS12=1;
- public static final int TYPE_KEYSTORE=2;
- public static final int TYPE_USERPASS = 3;
- public static final int TYPE_STATICKEYS = 4;
- public static final int TYPE_USERPASS_CERTIFICATES = 5;
- public static final int TYPE_USERPASS_PKCS12 = 6;
- public static final int TYPE_USERPASS_KEYSTORE = 7;
-
- public static final int X509_VERIFY_TLSREMOTE=0;
- public static final int X509_VERIFY_TLSREMOTE_COMPAT_NOREMAPPING=1;
- public static final int X509_VERIFY_TLSREMOTE_DN=2;
- public static final int X509_VERIFY_TLSREMOTE_RDN=3;
- public static final int X509_VERIFY_TLSREMOTE_RDN_PREFIX=4;
-
-
-
- // Don't change this, not all parts of the program use this constant
- public static final String EXTRA_PROFILEUUID = "de.blinkt.openvpn.profileUUID";
- public static final String INLINE_TAG = "[[INLINE]]";
- private static final String OVPNCONFIGFILE = "android.conf";
-
- public transient String mTransientPW=null;
- public transient String mTransientPCKS12PW=null;
- private transient PrivateKey mPrivateKey;
-
- // variable named wrong and should haven beeen transient
- // but needs to keep wrong name to guarante loading of old
- // profiles
- public transient boolean profileDleted=false;
-
-
- public static String DEFAULT_DNS1="8.8.8.8";
- public static String DEFAULT_DNS2="8.8.4.4";
-
- // Public attributes, since I got mad with getter/setter
- // set members to default values
- private UUID mUuid;
- public int mAuthenticationType = TYPE_KEYSTORE ;
- public String mName;
- public String mAlias;
- public String mClientCertFilename;
- public String mTLSAuthDirection="";
- public String mTLSAuthFilename;
- public String mClientKeyFilename;
- public String mCaFilename;
- public boolean mUseLzo=true;
- public String mServerPort= "1194" ;
- public boolean mUseUdp = true;
- public String mPKCS12Filename;
- public String mPKCS12Password;
- public boolean mUseTLSAuth = false;
- public String mServerName = "openvpn.blinkt.de" ;
- public String mDNS1=DEFAULT_DNS1;
- public String mDNS2=DEFAULT_DNS2;
- public String mIPv4Address;
- public String mIPv6Address;
- public boolean mOverrideDNS=false;
- public String mSearchDomain="blinkt.de";
- public boolean mUseDefaultRoute=true;
- public boolean mUsePull=true;
- public String mCustomRoutes;
- public boolean mCheckRemoteCN=false;
- public boolean mExpectTLSCert=true;
- public String mRemoteCN="";
- public String mPassword="";
- public String mUsername="";
- public boolean mRoutenopull=false;
- public boolean mUseRandomHostname=false;
- public boolean mUseFloat=false;
- public boolean mUseCustomConfig=false;
- public String mCustomConfigOptions="";
- public String mVerb="1";
- public String mCipher="";
- public boolean mNobind=false;
- public boolean mUseDefaultRoutev6=true;
- public String mCustomRoutesv6="";
- public String mKeyPassword="";
- public boolean mPersistTun = false;
- public String mConnectRetryMax="5";
- public String mConnectRetry="5";
- public boolean mUserEditable=true;
- public String mAuth="";
- public int mX509AuthType=X509_VERIFY_TLSREMOTE_RDN;
-
- public static final String MINIVPN = "miniopenvpn";
-
- public void clearDefaults() {
- mServerName="unkown";
- mUsePull=false;
- mUseLzo=false;
- mUseDefaultRoute=false;
- mUseDefaultRoutev6=false;
- mExpectTLSCert=false;
- mPersistTun = false;
- }
-
-
- public static String openVpnEscape(String unescaped) {
- if(unescaped==null)
- return null;
- String escapedString = unescaped.replace("\\", "\\\\");
- escapedString = escapedString.replace("\"","\\\"");
- escapedString = escapedString.replace("\n","\\n");
-
- if (escapedString.equals(unescaped) && !escapedString.contains(" ") && !escapedString.contains("#"))
- return unescaped;
- else
- return '"' + escapedString + '"';
- }
-
- public VpnProfile(String name) {
- mUuid = UUID.randomUUID();
- mName = name;
- }
-
- public UUID getUUID() {
- return mUuid;
-
- }
-
- public String getName() {
- return mName;
- }
-
-
- public String getConfigFile(Context context, boolean configForOvpn3)
- {
-
- File cacheDir= context.getCacheDir();
- String cfg="";
-
- // Enable managment interface
- cfg += "# Enables connection to GUI\n";
- cfg += "management ";
-
- cfg +=cacheDir.getAbsolutePath() + "/" + "mgmtsocket";
- cfg += " unix\n";
- cfg += "management-client\n";
- // Not needed, see updated man page in 2.3
- //cfg += "management-signal\n";
- cfg += "management-query-passwords\n";
- cfg += "management-hold\n\n";
+public class VpnProfile implements Serializable {
+ // Note that this class cannot be moved to core where it belongs since
+ // the profile loading depends on it being here
+ // The Serializable documentation mentions that class name change are possible
+ // but the how is unclear
+ //
+
+ public static final int TYPE_CERTIFICATES = 0;
+ public static final int TYPE_PKCS12 = 1;
+ public static final int TYPE_KEYSTORE = 2;
+ public static final int TYPE_USERPASS = 3;
+ public static final int TYPE_STATICKEYS = 4;
+ public static final int TYPE_USERPASS_CERTIFICATES = 5;
+ public static final int TYPE_USERPASS_PKCS12 = 6;
+ public static final int TYPE_USERPASS_KEYSTORE = 7;
+ public static final int X509_VERIFY_TLSREMOTE = 0;
+ public static final int X509_VERIFY_TLSREMOTE_COMPAT_NOREMAPPING = 1;
+ public static final int X509_VERIFY_TLSREMOTE_DN = 2;
+ public static final int X509_VERIFY_TLSREMOTE_RDN = 3;
+ public static final int X509_VERIFY_TLSREMOTE_RDN_PREFIX = 4;
+ // Don't change this, not all parts of the program use this constant
+ public static final String EXTRA_PROFILEUUID = "de.blinkt.openvpn.profileUUID";
+ public static final String INLINE_TAG = "[[INLINE]]";
+ public static final String MINIVPN = "miniopenvpn";
+ private static final long serialVersionUID = 7085688938959334563L;
+ private static final String OVPNCONFIGFILE = "android.conf";
+ public static String DEFAULT_DNS1 = "8.8.8.8";
+ public static String DEFAULT_DNS2 = "8.8.4.4";
+ public transient String mTransientPW = null;
+ public transient String mTransientPCKS12PW = null;
+ // variable named wrong and should haven beeen transient
+ // but needs to keep wrong name to guarante loading of old
+ // profiles
+ public transient boolean profileDleted = false;
+ public int mAuthenticationType = TYPE_KEYSTORE;
+ public String mName;
+ public String mAlias;
+ public String mClientCertFilename;
+ public String mTLSAuthDirection = "";
+ public String mTLSAuthFilename;
+ public String mClientKeyFilename;
+ public String mCaFilename;
+ public boolean mUseLzo = true;
+ public String mServerPort = "1194";
+ public boolean mUseUdp = true;
+ public String mPKCS12Filename;
+ public String mPKCS12Password;
+ public boolean mUseTLSAuth = false;
+ public String mServerName = "openvpn.blinkt.de";
+ public String mDNS1 = DEFAULT_DNS1;
+ public String mDNS2 = DEFAULT_DNS2;
+ public String mIPv4Address;
+ public String mIPv6Address;
+ public boolean mOverrideDNS = false;
+ public String mSearchDomain = "blinkt.de";
+ public boolean mUseDefaultRoute = true;
+ public boolean mUsePull = true;
+ public String mCustomRoutes;
+ public boolean mCheckRemoteCN = false;
+ public boolean mExpectTLSCert = true;
+ public String mRemoteCN = "";
+ public String mPassword = "";
+ public String mUsername = "";
+ public boolean mRoutenopull = false;
+ public boolean mUseRandomHostname = false;
+ public boolean mUseFloat = false;
+ public boolean mUseCustomConfig = false;
+ public String mCustomConfigOptions = "";
+ public String mVerb = "1";
+ public String mCipher = "";
+ public boolean mNobind = false;
+ public boolean mUseDefaultRoutev6 = true;
+ public String mCustomRoutesv6 = "";
+ public String mKeyPassword = "";
+ public boolean mPersistTun = false;
+ public String mConnectRetryMax = "5";
+ public String mConnectRetry = "5";
+ public boolean mUserEditable = true;
+ public String mAuth = "";
+ public int mX509AuthType = X509_VERIFY_TLSREMOTE_RDN;
+ private transient PrivateKey mPrivateKey;
+ // Public attributes, since I got mad with getter/setter
+ // set members to default values
+ private UUID mUuid;
+
+ public VpnProfile(String name) {
+ mUuid = UUID.randomUUID();
+ mName = name;
+ }
+
+ public static String openVpnEscape(String unescaped) {
+ if (unescaped == null)
+ return null;
+ String escapedString = unescaped.replace("\\", "\\\\");
+ escapedString = escapedString.replace("\"", "\\\"");
+ escapedString = escapedString.replace("\n", "\\n");
+
+ if (escapedString.equals(unescaped) && !escapedString.contains(" ") && !escapedString.contains("#"))
+ return unescaped;
+ else
+ return '"' + escapedString + '"';
+ }
+
+ public void clearDefaults() {
+ mServerName = "unkown";
+ mUsePull = false;
+ mUseLzo = false;
+ mUseDefaultRoute = false;
+ mUseDefaultRoutev6 = false;
+ mExpectTLSCert = false;
+ mPersistTun = false;
+ }
+
+ public UUID getUUID() {
+ return mUuid;
+
+ }
+
+ public String getName() {
+ return mName;
+ }
+
+ public String getConfigFile(Context context, boolean configForOvpn3) {
+
+ File cacheDir = context.getCacheDir();
+ String cfg = "";
+
+ // Enable managment interface
+ cfg += "# Enables connection to GUI\n";
+ cfg += "management ";
+
+ cfg += cacheDir.getAbsolutePath() + "/" + "mgmtsocket";
+ cfg += " unix\n";
+ cfg += "management-client\n";
+ // Not needed, see updated man page in 2.3
+ //cfg += "management-signal\n";
+ cfg += "management-query-passwords\n";
+ cfg += "management-hold\n\n";
cfg += getVersionEnvString(context);
- cfg+="# Log window is better readable this way\n";
- cfg+="suppress-timestamps\n";
+ cfg += "# Log window is better readable this way\n";
+ cfg += "suppress-timestamps\n";
+
+
+ boolean useTLSClient = (mAuthenticationType != TYPE_STATICKEYS);
+
+ if (useTLSClient && mUsePull)
+ cfg += "client\n";
+ else if (mUsePull)
+ cfg += "pull\n";
+ else if (useTLSClient)
+ cfg += "tls-client\n";
+
+
+ cfg += "verb " + mVerb + "\n";
+
+ if (mConnectRetryMax == null) {
+ mConnectRetryMax = "5";
+ }
+
+ if (!mConnectRetryMax.equals("-1"))
+ cfg += "connect-retry-max " + mConnectRetryMax + "\n";
+
+ if (mConnectRetry == null)
+ mConnectRetry = "5";
+
+
+ cfg += "connect-retry " + mConnectRetry + "\n";
+
+ cfg += "resolv-retry 60\n";
+
+
+ // We cannot use anything else than tun
+ cfg += "dev tun\n";
+
+ // Server Address
+ cfg += "remote ";
+ cfg += mServerName;
+ cfg += " ";
+ cfg += mServerPort;
+ if (mUseUdp)
+ cfg += " udp\n";
+ else
+ cfg += " tcp-client\n";
+
+
+ switch (mAuthenticationType) {
+ case VpnProfile.TYPE_USERPASS_CERTIFICATES:
+ cfg += "auth-user-pass\n";
+ case VpnProfile.TYPE_CERTIFICATES:
+ // Ca
+ cfg += insertFileData("ca", mCaFilename);
+
+ // Client Cert + Key
+ cfg += insertFileData("key", mClientKeyFilename);
+ cfg += insertFileData("cert", mClientCertFilename);
+
+ break;
+ case VpnProfile.TYPE_USERPASS_PKCS12:
+ cfg += "auth-user-pass\n";
+ case VpnProfile.TYPE_PKCS12:
+ cfg += insertFileData("pkcs12", mPKCS12Filename);
+ break;
+
+ case VpnProfile.TYPE_USERPASS_KEYSTORE:
+ cfg += "auth-user-pass\n";
+ case VpnProfile.TYPE_KEYSTORE:
+ if (!configForOvpn3) {
+ String[] ks = getKeyStoreCertificates(context);
+ cfg += "### From Keystore ####\n";
+ if (ks != null) {
+ cfg += "<ca>\n" + ks[0] + "</ca>\n";
+ if (ks[1] != null)
+ cfg += "<extra-certs>\n" + ks[1] + "<extra-certs>\n";
+ cfg += "<cert>\n" + ks[2] + "</cert>\n";
+ cfg += "management-external-key\n";
+ } else {
+ cfg += context.getString(R.string.keychain_access) + "\n";
+ if (Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN)
+ if (!mAlias.matches("^[a-zA-Z0-9]$"))
+ cfg += context.getString(R.string.jelly_keystore_alphanumeric_bug) + "\n";
+ }
+ }
+ break;
+ case VpnProfile.TYPE_USERPASS:
+ cfg += "auth-user-pass\n";
+ cfg += insertFileData("ca", mCaFilename);
+ }
+
+ if (mUseLzo) {
+ cfg += "comp-lzo\n";
+ }
+
+ if (mUseTLSAuth) {
+ if (mAuthenticationType == TYPE_STATICKEYS)
+ cfg += insertFileData("secret", mTLSAuthFilename);
+ else
+ cfg += insertFileData("tls-auth", mTLSAuthFilename);
+
+ if (nonNull(mTLSAuthDirection)) {
+ cfg += "key-direction ";
+ cfg += mTLSAuthDirection;
+ cfg += "\n";
+ }
+
+ }
+
+ if (!mUsePull) {
+ if (nonNull(mIPv4Address))
+ cfg += "ifconfig " + cidrToIPAndNetmask(mIPv4Address) + "\n";
+ if (nonNull(mIPv6Address))
+ cfg += "ifconfig-ipv6 " + mIPv6Address + "\n";
+ }
+ if (mUsePull && mRoutenopull)
+ cfg += "route-nopull\n";
+
+ String routes = "";
+ int numroutes = 0;
+ if (mUseDefaultRoute)
+ routes += "route 0.0.0.0 0.0.0.0\n";
+ else
+ for (String route : getCustomRoutes()) {
+ routes += "route " + route + "\n";
+ numroutes++;
+ }
+
+
+ if (mUseDefaultRoutev6)
+ cfg += "route-ipv6 ::/0\n";
+ else
+ for (String route : getCustomRoutesv6()) {
+ routes += "route-ipv6 " + route + "\n";
+ numroutes++;
+ }
+
+ // Round number to next 100
+ if (numroutes > 90) {
+ numroutes = ((numroutes / 100) + 1) * 100;
+ cfg += "# Alot of routes are set, increase max-routes\n";
+ cfg += "max-routes " + numroutes + "\n";
+ }
+ cfg += routes;
- boolean useTLSClient = (mAuthenticationType != TYPE_STATICKEYS);
+ if (mOverrideDNS || !mUsePull) {
+ if (nonNull(mDNS1))
+ cfg += "dhcp-option DNS " + mDNS1 + "\n";
+ if (nonNull(mDNS2))
+ cfg += "dhcp-option DNS " + mDNS2 + "\n";
+ if (nonNull(mSearchDomain))
+ cfg += "dhcp-option DOMAIN " + mSearchDomain + "\n";
- if(useTLSClient && mUsePull)
- cfg+="client\n";
- else if (mUsePull)
- cfg+="pull\n";
- else if(useTLSClient)
- cfg+="tls-client\n";
+ }
+ if (mNobind)
+ cfg += "nobind\n";
- cfg+="verb " + mVerb + "\n";
- if(mConnectRetryMax ==null) {
- mConnectRetryMax="5";
- }
+ // Authentication
+ if (mCheckRemoteCN) {
+ if (mRemoteCN == null || mRemoteCN.equals(""))
+ cfg += "verify-x509-name " + mServerName + " name\n";
+ else
+ switch (mX509AuthType) {
- if(!mConnectRetryMax.equals("-1"))
- cfg+="connect-retry-max " + mConnectRetryMax+ "\n";
+ // 2.2 style x509 checks
+ case X509_VERIFY_TLSREMOTE_COMPAT_NOREMAPPING:
+ cfg += "compat-names no-remapping\n";
+ case X509_VERIFY_TLSREMOTE:
+ cfg += "tls-remote " + openVpnEscape(mRemoteCN) + "\n";
+ break;
- if(mConnectRetry==null)
- mConnectRetry="5";
+ case X509_VERIFY_TLSREMOTE_RDN:
+ cfg += "verify-x509-name " + openVpnEscape(mRemoteCN) + " name\n";
+ break;
+ case X509_VERIFY_TLSREMOTE_RDN_PREFIX:
+ cfg += "verify-x509-name " + openVpnEscape(mRemoteCN) + " name-prefix\n";
+ break;
- cfg+="connect-retry " + mConnectRetry + "\n";
+ case X509_VERIFY_TLSREMOTE_DN:
+ cfg += "verify-x509-name " + openVpnEscape(mRemoteCN) + "\n";
+ break;
+ }
+ }
+ if (mExpectTLSCert)
+ cfg += "remote-cert-tls server\n";
- cfg+="resolv-retry 60\n";
+ if (nonNull(mCipher)) {
+ cfg += "cipher " + mCipher + "\n";
+ }
+ if (nonNull(mAuth)) {
+ cfg += "auth " + mAuth + "\n";
+ }
- // We cannot use anything else than tun
- cfg+="dev tun\n";
+ // Obscure Settings dialog
+ if (mUseRandomHostname)
+ cfg += "#my favorite options :)\nremote-random-hostname\n";
- // Server Address
- cfg+="remote ";
- cfg+=mServerName;
- cfg+=" ";
- cfg+=mServerPort;
- if(mUseUdp)
- cfg+=" udp\n";
- else
- cfg+=" tcp-client\n";
-
-
-
-
- switch(mAuthenticationType) {
- case VpnProfile.TYPE_USERPASS_CERTIFICATES:
- cfg+="auth-user-pass\n";
- case VpnProfile.TYPE_CERTIFICATES:
- // Ca
- cfg+=insertFileData("ca",mCaFilename);
-
- // Client Cert + Key
- cfg+=insertFileData("key",mClientKeyFilename);
- cfg+=insertFileData("cert",mClientCertFilename);
+ if (mUseFloat)
+ cfg += "float\n";
- break;
- case VpnProfile.TYPE_USERPASS_PKCS12:
- cfg+="auth-user-pass\n";
- case VpnProfile.TYPE_PKCS12:
- cfg+=insertFileData("pkcs12",mPKCS12Filename);
- break;
-
- case VpnProfile.TYPE_USERPASS_KEYSTORE:
- cfg+="auth-user-pass\n";
- case VpnProfile.TYPE_KEYSTORE:
- if(!configForOvpn3) {
- String[] ks =getKeyStoreCertificates(context);
- cfg+="### From Keystore ####\n";
- if(ks != null) {
- cfg+="<ca>\n" + ks[0] + "</ca>\n";
- cfg+="<cert>\n" + ks[0] + "</cert>\n";
- cfg+="management-external-key\n";
- } else {
- cfg += context.getString(R.string.keychain_access) +"\n";
- if(Build.VERSION.SDK_INT==Build.VERSION_CODES.JELLY_BEAN)
- if(!mAlias.matches("^[a-zA-Z0-9]$"))
- cfg += context.getString(R.string.jelly_keystore_alphanumeric_bug)+ "\n";
- }
- }
- break;
- case VpnProfile.TYPE_USERPASS:
- cfg+="auth-user-pass\n";
- cfg+=insertFileData("ca",mCaFilename);
- }
-
- if(mUseLzo) {
- cfg+="comp-lzo\n";
- }
-
- if(mUseTLSAuth) {
- if(mAuthenticationType==TYPE_STATICKEYS)
- cfg+=insertFileData("secret",mTLSAuthFilename);
- else
- cfg+=insertFileData("tls-auth",mTLSAuthFilename);
-
- if(nonNull(mTLSAuthDirection)) {
- cfg+= "key-direction ";
- cfg+= mTLSAuthDirection;
- cfg+="\n";
- }
-
- }
-
- if(!mUsePull ) {
- if(nonNull(mIPv4Address))
- cfg +="ifconfig " + cidrToIPAndNetmask(mIPv4Address) + "\n";
-
- if(nonNull(mIPv6Address))
- cfg +="ifconfig-ipv6 " + mIPv6Address + "\n";
- }
-
- if(mUsePull && mRoutenopull)
- cfg += "route-nopull\n";
-
- String routes = "";
- int numroutes=0;
- if(mUseDefaultRoute)
- routes += "route 0.0.0.0 0.0.0.0\n";
- else
- for(String route:getCustomRoutes()) {
- routes += "route " + route + "\n";
- numroutes++;
- }
-
-
- if(mUseDefaultRoutev6)
- cfg += "route-ipv6 ::/0\n";
- else
- for(String route:getCustomRoutesv6()) {
- routes += "route-ipv6 " + route + "\n";
- numroutes++;
- }
-
- // Round number to next 100
- if(numroutes> 90) {
- numroutes = ((numroutes / 100)+1) * 100;
- cfg+="# Alot of routes are set, increase max-routes\n";
- cfg+="max-routes " + numroutes + "\n";
- }
- cfg+=routes;
-
- if(mOverrideDNS || !mUsePull) {
- if(nonNull(mDNS1))
- cfg+="dhcp-option DNS " + mDNS1 + "\n";
- if(nonNull(mDNS2))
- cfg+="dhcp-option DNS " + mDNS2 + "\n";
- if(nonNull(mSearchDomain))
- cfg+="dhcp-option DOMAIN " + mSearchDomain + "\n";
-
- }
-
- if(mNobind)
- cfg+="nobind\n";
-
-
-
- // Authentication
- if(mCheckRemoteCN) {
- if(mRemoteCN == null || mRemoteCN.equals("") )
- cfg+="verify-x509-name " + mServerName + " name\n";
- else
- switch (mX509AuthType) {
-
- // 2.2 style x509 checks
- case X509_VERIFY_TLSREMOTE_COMPAT_NOREMAPPING:
- cfg+="compat-names no-remapping\n";
- case X509_VERIFY_TLSREMOTE:
- cfg+="tls-remote " + openVpnEscape(mRemoteCN) + "\n";
- break;
-
- case X509_VERIFY_TLSREMOTE_RDN:
- cfg+="verify-x509-name " + openVpnEscape(mRemoteCN) + " name\n";
- break;
-
- case X509_VERIFY_TLSREMOTE_RDN_PREFIX:
- cfg+="verify-x509-name " + openVpnEscape(mRemoteCN) + " name-prefix\n";
- break;
-
- case X509_VERIFY_TLSREMOTE_DN:
- cfg+="verify-x509-name " + openVpnEscape(mRemoteCN) + "\n";
- break;
- }
- }
- if(mExpectTLSCert)
- cfg += "remote-cert-tls server\n";
-
-
- if(nonNull(mCipher)){
- cfg += "cipher " + mCipher + "\n";
- }
-
- if(nonNull(mAuth)) {
- cfg += "auth " + mAuth + "\n";
- }
+ if (mPersistTun) {
+ cfg += "persist-tun\n";
+ cfg += "# persist-tun also sets persist-remote-ip to avoid DNS resolve problem\n";
+ cfg += "persist-remote-ip\n";
+ }
- // Obscure Settings dialog
- if(mUseRandomHostname)
- cfg += "#my favorite options :)\nremote-random-hostname\n";
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
+ boolean usesystemproxy = prefs.getBoolean("usesystemproxy", true);
+ if (usesystemproxy) {
+ cfg += "# Use system proxy setting\n";
+ cfg += "management-query-proxy\n";
+ }
- if(mUseFloat)
- cfg+= "float\n";
-
- if(mPersistTun) {
- cfg+= "persist-tun\n";
- cfg+= "# persist-tun also sets persist-remote-ip to avoid DNS resolve problem\n";
- cfg+= "persist-remote-ip\n";
- }
-
- SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
- boolean usesystemproxy = prefs.getBoolean("usesystemproxy", true);
- if(usesystemproxy) {
- cfg+= "# Use system proxy setting\n";
- cfg+= "management-query-proxy\n";
- }
-
-
- if(mUseCustomConfig) {
- cfg += "# Custom configuration options\n";
- cfg += "# You are on your on own here :)\n";
- cfg += mCustomConfigOptions;
- cfg += "\n";
- }
+ if (mUseCustomConfig) {
+ cfg += "# Custom configuration options\n";
+ cfg += "# You are on your on own here :)\n";
+ cfg += mCustomConfigOptions;
+ cfg += "\n";
+
+ }
-
- return cfg;
- }
+ return cfg;
+ }
private String getVersionEnvString(Context c) {
- String version="unknown";
+ String version = "unknown";
try {
PackageInfo packageinfo = c.getPackageManager().getPackageInfo(c.getPackageName(), 0);
version = packageinfo.versionName;
} catch (PackageManager.NameNotFoundException e) {
}
- return String.format(Locale.US,"setenv IV_OPENVPN_GUI_VERSION \"%s %s\"\n",c.getPackageName(),version);
+ return String.format(Locale.US, "setenv IV_OPENVPN_GUI_VERSION \"%s %s\"\n", c.getPackageName(), version);
}
//! Put inline data inline and other data as normal escaped filename
- private String insertFileData(String cfgentry, String filedata) {
- if(filedata==null) {
- // TODO: generate good error
- return String.format("%s %s\n",cfgentry,"missing");
- }else if(filedata.startsWith(VpnProfile.INLINE_TAG)){
- String datawoheader = filedata.substring(VpnProfile.INLINE_TAG.length());
- return String.format(Locale.ENGLISH,"<%s>\n%s\n</%s>\n",cfgentry,datawoheader,cfgentry);
- } else {
- return String.format(Locale.ENGLISH,"%s %s\n",cfgentry,openVpnEscape(filedata));
- }
- }
-
- private boolean nonNull(String val) {
- if(val == null || val.equals(""))
- return false;
- else
- return true;
- }
-
- private Collection<String> getCustomRoutes() {
- Vector<String> cidrRoutes=new Vector<String>();
- if(mCustomRoutes==null) {
- // No routes set, return empty vector
- return cidrRoutes;
- }
- for(String route:mCustomRoutes.split("[\n \t]")) {
- if(!route.equals("")) {
- String cidrroute = cidrToIPAndNetmask(route);
- if(cidrRoutes == null)
- return null;
-
- cidrRoutes.add(cidrroute);
- }
- }
-
- return cidrRoutes;
- }
-
- private Collection<String> getCustomRoutesv6() {
- Vector<String> cidrRoutes=new Vector<String>();
- if(mCustomRoutesv6==null) {
- // No routes set, return empty vector
- return cidrRoutes;
- }
- for(String route:mCustomRoutesv6.split("[\n \t]")) {
- if(!route.equals("")) {
- cidrRoutes.add(route);
- }
- }
-
- return cidrRoutes;
- }
-
-
-
- private String cidrToIPAndNetmask(String route) {
- String[] parts = route.split("/");
-
- // No /xx, assume /32 as netmask
- if (parts.length ==1)
- parts = (route + "/32").split("/");
-
- if (parts.length!=2)
- return null;
- int len;
- try {
- len = Integer.parseInt(parts[1]);
- } catch(NumberFormatException ne) {
- return null;
- }
- if (len <0 || len >32)
- return null;
+ private String insertFileData(String cfgentry, String filedata) {
+ if (filedata == null) {
+ // TODO: generate good error
+ return String.format("%s %s\n", cfgentry, "missing");
+ } else if (filedata.startsWith(VpnProfile.INLINE_TAG)) {
+ String datawoheader = filedata.substring(VpnProfile.INLINE_TAG.length());
+ return String.format(Locale.ENGLISH, "<%s>\n%s\n</%s>\n", cfgentry, datawoheader, cfgentry);
+ } else {
+ return String.format(Locale.ENGLISH, "%s %s\n", cfgentry, openVpnEscape(filedata));
+ }
+ }
+ private boolean nonNull(String val) {
+ if (val == null || val.equals(""))
+ return false;
+ else
+ return true;
+ }
- long nm = 0xffffffffl;
- nm = (nm << (32-len)) & 0xffffffffl;
+ private Collection<String> getCustomRoutes() {
+ Vector<String> cidrRoutes = new Vector<String>();
+ if (mCustomRoutes == null) {
+ // No routes set, return empty vector
+ return cidrRoutes;
+ }
+ for (String route : mCustomRoutes.split("[\n \t]")) {
+ if (!route.equals("")) {
+ String cidrroute = cidrToIPAndNetmask(route);
+ if (cidrRoutes == null)
+ return null;
+
+ cidrRoutes.add(cidrroute);
+ }
+ }
- String netmask =String.format(Locale.ENGLISH,"%d.%d.%d.%d", (nm & 0xff000000) >> 24,(nm & 0xff0000) >> 16, (nm & 0xff00) >> 8 ,nm & 0xff );
- return parts[0] + " " + netmask;
- }
+ return cidrRoutes;
+ }
+ private Collection<String> getCustomRoutesv6() {
+ Vector<String> cidrRoutes = new Vector<String>();
+ if (mCustomRoutesv6 == null) {
+ // No routes set, return empty vector
+ return cidrRoutes;
+ }
+ for (String route : mCustomRoutesv6.split("[\n \t]")) {
+ if (!route.equals("")) {
+ cidrRoutes.add(route);
+ }
+ }
+ return cidrRoutes;
+ }
- private String[] buildOpenvpnArgv(File cacheDir)
- {
- Vector<String> args = new Vector<String>();
+ private String cidrToIPAndNetmask(String route) {
+ String[] parts = route.split("/");
- // Add fixed paramenters
- //args.add("/data/data/de.blinkt.openvpn/lib/openvpn");
- args.add(cacheDir.getAbsolutePath() +"/" + VpnProfile.MINIVPN);
-
- args.add("--config");
- args.add(cacheDir.getAbsolutePath() + "/" + OVPNCONFIGFILE);
-
-
- return args.toArray(new String[args.size()]);
- }
-
- public Intent prepareIntent(Context context) {
- String prefix = context.getPackageName();
-
- Intent intent = new Intent(context,OpenVpnService.class);
-
- if(mAuthenticationType == VpnProfile.TYPE_KEYSTORE || mAuthenticationType == VpnProfile.TYPE_USERPASS_KEYSTORE) {
- if(getKeyStoreCertificates(context)==null)
- return null;
- }
-
- intent.putExtra(prefix + ".ARGV" , buildOpenvpnArgv(context.getCacheDir()));
- intent.putExtra(prefix + ".profileUUID", mUuid.toString());
+ // No /xx, assume /32 as netmask
+ if (parts.length == 1)
+ parts = (route + "/32").split("/");
- ApplicationInfo info = context.getApplicationInfo();
- intent.putExtra(prefix +".nativelib",info.nativeLibraryDir);
+ if (parts.length != 2)
+ return null;
+ int len;
+ try {
+ len = Integer.parseInt(parts[1]);
+ } catch (NumberFormatException ne) {
+ return null;
+ }
+ if (len < 0 || len > 32)
+ return null;
- try {
- FileWriter cfg = new FileWriter(context.getCacheDir().getAbsolutePath() + "/" + OVPNCONFIGFILE);
- cfg.write(getConfigFile(context,false));
- cfg.flush();
- cfg.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- return intent;
- }
+ long nm = 0xffffffffl;
+ nm = (nm << (32 - len)) & 0xffffffffl;
- String[] getKeyStoreCertificates(Context context) {
- PrivateKey privateKey = null;
- X509Certificate[] cachain=null;
- try {
- privateKey = KeyChain.getPrivateKey(context,mAlias);
- mPrivateKey = privateKey;
+ String netmask = String.format(Locale.ENGLISH, "%d.%d.%d.%d", (nm & 0xff000000) >> 24, (nm & 0xff0000) >> 16, (nm & 0xff00) >> 8, nm & 0xff);
+ return parts[0] + " " + netmask;
+ }
- cachain = KeyChain.getCertificateChain(context, mAlias);
- if(cachain.length <= 1 && !nonNull(mCaFilename))
- OpenVPN.logMessage(0, "", context.getString(R.string.keychain_nocacert));
+ private String[] buildOpenvpnArgv(File cacheDir) {
+ Vector<String> args = new Vector<String>();
+ // Add fixed paramenters
+ //args.add("/data/data/de.blinkt.openvpn/lib/openvpn");
+ args.add(cacheDir.getAbsolutePath() + "/" + VpnProfile.MINIVPN);
- if(nonNull(mCaFilename)) {
- try {
- Certificate cacert = X509Utils.getCertificateFromFile(mCaFilename);
- X509Certificate[] newcachain = new X509Certificate[cachain.length+1];
- System.arraycopy(cachain, 0, newcachain, 0, cachain.length);
+ args.add("--config");
+ args.add(cacheDir.getAbsolutePath() + "/" + OVPNCONFIGFILE);
- newcachain[cachain.length-1]=(X509Certificate) cacert;
- cachain=newcachain;
- } catch (Exception e) {
- OpenVPN.logError("Could not read CA certificate" + e.getLocalizedMessage());
- }
- }
+ return args.toArray(new String[args.size()]);
+ }
+ public Intent prepareIntent(Context context) {
+ String prefix = context.getPackageName();
+ Intent intent = new Intent(context, OpenVpnService.class);
- StringWriter caout = new StringWriter();
+ if (mAuthenticationType == VpnProfile.TYPE_KEYSTORE || mAuthenticationType == VpnProfile.TYPE_USERPASS_KEYSTORE) {
+ if (getKeyStoreCertificates(context) == null)
+ return null;
+ }
- PemWriter pw = new PemWriter(caout);
- for(X509Certificate cert:cachain) {
- pw.writeObject(new PemObject("CERTIFICATE", cert.getEncoded()));
- }
- pw.close();
+ intent.putExtra(prefix + ".ARGV", buildOpenvpnArgv(context.getCacheDir()));
+ intent.putExtra(prefix + ".profileUUID", mUuid.toString());
+ ApplicationInfo info = context.getApplicationInfo();
+ intent.putExtra(prefix + ".nativelib", info.nativeLibraryDir);
+ try {
+ FileWriter cfg = new FileWriter(context.getCacheDir().getAbsolutePath() + "/" + OVPNCONFIGFILE);
+ cfg.write(getConfigFile(context, false));
+ cfg.flush();
+ cfg.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
- StringWriter certout = new StringWriter();
-
-
- if(cachain.length>= 1){
- X509Certificate usercert = cachain[0];
-
- PemWriter upw = new PemWriter(certout);
- upw.writeObject(new PemObject("CERTIFICATE", usercert.getEncoded()));
- upw.close();
-
- }
-
- return new String[] {caout.toString(),certout.toString()};
- } catch (InterruptedException e) {
- e.printStackTrace();
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- } catch (CertificateException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- } catch (KeyChainException e) {
- OpenVPN.logMessage(0,"",context.getString(R.string.keychain_access));
- if(Build.VERSION.SDK_INT==Build.VERSION_CODES.JELLY_BEAN){
- if(!mAlias.matches("^[a-zA-Z0-9]$")) {
- OpenVPN.logError(R.string.jelly_keystore_alphanumeric_bug);
- }
- }
- }
- return null;
- }
-
-
- //! Return an error if somethign is wrong
- public int checkProfile(Context context) {
- if(mAuthenticationType==TYPE_KEYSTORE || mAuthenticationType==TYPE_USERPASS_KEYSTORE) {
- if(mAlias==null)
- return R.string.no_keystore_cert_selected;
- }
-
- if(!mUsePull) {
- if(mIPv4Address == null || cidrToIPAndNetmask(mIPv4Address) == null)
- return R.string.ipv4_format_error;
- }
- if(!mUseDefaultRoute && getCustomRoutes()==null)
- return R.string.custom_route_format_error;
-
- // Everything okay
- return R.string.no_error_found;
-
- }
-
-
-
- //! Openvpn asks for a "Private Key", this should be pkcs12 key
- //
- public String getPasswordPrivateKey() {
- if(mTransientPCKS12PW!=null) {
- String pwcopy = mTransientPCKS12PW;
- mTransientPCKS12PW=null;
- return pwcopy;
- }
- switch (mAuthenticationType) {
- case TYPE_PKCS12:
- case TYPE_USERPASS_PKCS12:
- return mPKCS12Password;
-
- case TYPE_CERTIFICATES:
- case TYPE_USERPASS_CERTIFICATES:
- return mKeyPassword;
-
- case TYPE_USERPASS:
- case TYPE_STATICKEYS:
- default:
- return null;
- }
- }
- boolean isUserPWAuth() {
- switch(mAuthenticationType) {
- case TYPE_USERPASS:
- case TYPE_USERPASS_CERTIFICATES:
- case TYPE_USERPASS_KEYSTORE:
- case TYPE_USERPASS_PKCS12:
- return true;
- default:
- return false;
-
- }
- }
-
-
- public boolean requireTLSKeyPassword() {
- if(!nonNull(mClientKeyFilename))
- return false;
-
- String data = "";
- if(mClientKeyFilename.startsWith(INLINE_TAG))
- data = mClientKeyFilename;
- else {
- char[] buf = new char[2048];
- FileReader fr;
- try {
- fr = new FileReader(mClientKeyFilename);
- int len = fr.read(buf);
- while(len > 0 ) {
- data += new String(buf,0,len);
- len = fr.read(buf);
- }
- fr.close();
- } catch (FileNotFoundException e) {
- return false;
- } catch (IOException e) {
- return false;
- }
-
- }
-
- if(data.contains("Proc-Type: 4,ENCRYPTED"))
- return true;
- else if(data.contains("-----BEGIN ENCRYPTED PRIVATE KEY-----"))
- return true;
- else
- return false;
- }
-
- public int needUserPWInput() {
- if((mAuthenticationType == TYPE_PKCS12 || mAuthenticationType == TYPE_USERPASS_PKCS12)&&
- (mPKCS12Password == null || mPKCS12Password.equals(""))) {
- if(mTransientPCKS12PW==null)
- return R.string.pkcs12_file_encryption_key;
- }
-
- if(mAuthenticationType == TYPE_CERTIFICATES || mAuthenticationType == TYPE_USERPASS_CERTIFICATES) {
- if(requireTLSKeyPassword() && !nonNull(mKeyPassword))
- if(mTransientPCKS12PW==null) {
- return R.string.private_key_password;
- }
- }
-
- if (isUserPWAuth() && !(nonNull(mUsername) && (nonNull(mPassword) || mTransientPW!=null))) {
- return R.string.password;
- }
- return 0;
- }
-
- public String getPasswordAuth() {
- if(mTransientPW!=null) {
- String pwcopy = mTransientPW;
- mTransientPW=null;
- return pwcopy;
- } else {
- return mPassword;
- }
- }
-
-
- // Used by the Array Adapter
- @Override
- public String toString() {
- return mName;
- }
-
-
- public String getUUIDString() {
- return mUuid.toString();
- }
-
-
- public PrivateKey getKeystoreKey() {
- return mPrivateKey;
- }
-
- public String getSignedData(String b64data) {
- PrivateKey privkey = getKeystoreKey();
- Exception err =null;
-
- byte[] data = Base64.decode(b64data, Base64.DEFAULT);
-
- // The Jelly Bean *evil* Hack
- // 4.2 implements the RSA/ECB/PKCS1PADDING in the OpenSSLprovider
- if(Build.VERSION.SDK_INT==Build.VERSION_CODES.JELLY_BEAN){
- return processSignJellyBeans(privkey,data);
- }
-
-
- try{
-
-
- Cipher rsasinger = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
-
- rsasinger.init(Cipher.ENCRYPT_MODE, privkey);
-
- byte[] signed_bytes = rsasinger.doFinal(data);
- return Base64.encodeToString(signed_bytes, Base64.NO_WRAP);
-
- } catch (NoSuchAlgorithmException e){
- err =e;
- } catch (InvalidKeyException e) {
- err =e;
- } catch (NoSuchPaddingException e) {
- err =e;
- } catch (IllegalBlockSizeException e) {
- err =e;
- } catch (BadPaddingException e) {
- err =e;
- }
- if(err !=null) {
- OpenVPN.logError(R.string.error_rsa_sign,err.getClass().toString(),err.getLocalizedMessage());
- }
- return null;
-
- }
-
-
- private String processSignJellyBeans(PrivateKey privkey, byte[] data) {
- Exception err =null;
- try {
- Method[] allm = privkey.getClass().getSuperclass().getDeclaredMethods();
- System.out.println(allm);
- Method getKey = privkey.getClass().getSuperclass().getDeclaredMethod("getOpenSSLKey");
- getKey.setAccessible(true);
-
- // Real object type is OpenSSLKey
- Object opensslkey = getKey.invoke(privkey);
-
- getKey.setAccessible(false);
-
- Method getPkeyContext = opensslkey.getClass().getDeclaredMethod("getPkeyContext");
-
- // integer pointer to EVP_pkey
- getPkeyContext.setAccessible(true);
- int pkey = (Integer) getPkeyContext.invoke(opensslkey);
- getPkeyContext.setAccessible(false);
-
- byte[] signed_bytes = NativeUtils.rsasign(data, pkey);
- return Base64.encodeToString(signed_bytes, Base64.NO_WRAP);
-
- } catch (NoSuchMethodException e) {
- err=e;
- } catch (IllegalArgumentException e) {
- err=e;
- } catch (IllegalAccessException e) {
- err=e;
- } catch (InvocationTargetException e) {
- err=e;
- } catch (InvalidKeyException e) {
- err=e;
- }
- if(err !=null) {
- OpenVPN.logError(R.string.error_rsa_sign,err.getClass().toString(),err.getLocalizedMessage());
- }
- return null;
-
- }
+ return intent;
+ }
+ String[] getKeyStoreCertificates(Context context) {
+ PrivateKey privateKey = null;
+ X509Certificate[] cachain = null;
+ try {
+ privateKey = KeyChain.getPrivateKey(context, mAlias);
+ mPrivateKey = privateKey;
+
+ String keystoreChain = null;
+
+
+ cachain = KeyChain.getCertificateChain(context, mAlias);
+ if (cachain.length <= 1 && !nonNull(mCaFilename)) {
+ OpenVPN.logMessage(0, "", context.getString(R.string.keychain_nocacert));
+ } else {
+ StringWriter ksStringWriter = new StringWriter();
+
+ PemWriter pw = new PemWriter(ksStringWriter);
+ for (int i = 1; i < cachain.length; i++) {
+ X509Certificate cert = cachain[i];
+ pw.writeObject(new PemObject("CERTIFICATE", cert.getEncoded()));
+ }
+ pw.close();
+ keystoreChain = ksStringWriter.toString();
+ }
+
+
+ String caout = null;
+ if (nonNull(mCaFilename)) {
+ try {
+ Certificate cacert = X509Utils.getCertificateFromFile(mCaFilename);
+ StringWriter caoutWriter = new StringWriter();
+ PemWriter pw = new PemWriter(caoutWriter);
+
+ pw.writeObject(new PemObject("CERTIFICATE", cacert.getEncoded()));
+ pw.close();
+ caout= caoutWriter.toString();
+
+ } catch (Exception e) {
+ OpenVPN.logError("Could not read CA certificate" + e.getLocalizedMessage());
+ }
+ }
+
+
+ StringWriter certout = new StringWriter();
+
+
+ if (cachain.length >= 1) {
+ X509Certificate usercert = cachain[0];
+
+ PemWriter upw = new PemWriter(certout);
+ upw.writeObject(new PemObject("CERTIFICATE", usercert.getEncoded()));
+ upw.close();
+
+ }
+ String user = certout.toString();
+
+
+ String ca, extra;
+ if(caout==null) {
+ ca =keystoreChain;
+ extra=null;
+ } else {
+ ca = caout;
+ extra=keystoreChain;
+ }
+
+ return new String[]{ca, extra, user};
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ } catch (CertificateException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ } catch (KeyChainException e) {
+ OpenVPN.logMessage(0, "", context.getString(R.string.keychain_access));
+ if (Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN) {
+ if (!mAlias.matches("^[a-zA-Z0-9]$")) {
+ OpenVPN.logError(R.string.jelly_keystore_alphanumeric_bug);
+ }
+ }
+ }
+ return null;
+ }
+
+ //! Return an error if somethign is wrong
+ public int checkProfile(Context context) {
+ if (mAuthenticationType == TYPE_KEYSTORE || mAuthenticationType == TYPE_USERPASS_KEYSTORE) {
+ if (mAlias == null)
+ return R.string.no_keystore_cert_selected;
+ }
+
+ if (!mUsePull) {
+ if (mIPv4Address == null || cidrToIPAndNetmask(mIPv4Address) == null)
+ return R.string.ipv4_format_error;
+ }
+ if (!mUseDefaultRoute && getCustomRoutes() == null)
+ return R.string.custom_route_format_error;
+
+ // Everything okay
+ return R.string.no_error_found;
+
+ }
+
+ //! Openvpn asks for a "Private Key", this should be pkcs12 key
+ //
+ public String getPasswordPrivateKey() {
+ if (mTransientPCKS12PW != null) {
+ String pwcopy = mTransientPCKS12PW;
+ mTransientPCKS12PW = null;
+ return pwcopy;
+ }
+ switch (mAuthenticationType) {
+ case TYPE_PKCS12:
+ case TYPE_USERPASS_PKCS12:
+ return mPKCS12Password;
+
+ case TYPE_CERTIFICATES:
+ case TYPE_USERPASS_CERTIFICATES:
+ return mKeyPassword;
+
+ case TYPE_USERPASS:
+ case TYPE_STATICKEYS:
+ default:
+ return null;
+ }
+ }
+
+ boolean isUserPWAuth() {
+ switch (mAuthenticationType) {
+ case TYPE_USERPASS:
+ case TYPE_USERPASS_CERTIFICATES:
+ case TYPE_USERPASS_KEYSTORE:
+ case TYPE_USERPASS_PKCS12:
+ return true;
+ default:
+ return false;
+
+ }
+ }
+
+ public boolean requireTLSKeyPassword() {
+ if (!nonNull(mClientKeyFilename))
+ return false;
+
+ String data = "";
+ if (mClientKeyFilename.startsWith(INLINE_TAG))
+ data = mClientKeyFilename;
+ else {
+ char[] buf = new char[2048];
+ FileReader fr;
+ try {
+ fr = new FileReader(mClientKeyFilename);
+ int len = fr.read(buf);
+ while (len > 0) {
+ data += new String(buf, 0, len);
+ len = fr.read(buf);
+ }
+ fr.close();
+ } catch (FileNotFoundException e) {
+ return false;
+ } catch (IOException e) {
+ return false;
+ }
+
+ }
+
+ if (data.contains("Proc-Type: 4,ENCRYPTED"))
+ return true;
+ else if (data.contains("-----BEGIN ENCRYPTED PRIVATE KEY-----"))
+ return true;
+ else
+ return false;
+ }
+
+ public int needUserPWInput() {
+ if ((mAuthenticationType == TYPE_PKCS12 || mAuthenticationType == TYPE_USERPASS_PKCS12) &&
+ (mPKCS12Password == null || mPKCS12Password.equals(""))) {
+ if (mTransientPCKS12PW == null)
+ return R.string.pkcs12_file_encryption_key;
+ }
+
+ if (mAuthenticationType == TYPE_CERTIFICATES || mAuthenticationType == TYPE_USERPASS_CERTIFICATES) {
+ if (requireTLSKeyPassword() && !nonNull(mKeyPassword))
+ if (mTransientPCKS12PW == null) {
+ return R.string.private_key_password;
+ }
+ }
+
+ if (isUserPWAuth() && !(nonNull(mUsername) && (nonNull(mPassword) || mTransientPW != null))) {
+ return R.string.password;
+ }
+ return 0;
+ }
+
+ public String getPasswordAuth() {
+ if (mTransientPW != null) {
+ String pwcopy = mTransientPW;
+ mTransientPW = null;
+ return pwcopy;
+ } else {
+ return mPassword;
+ }
+ }
+
+ // Used by the Array Adapter
+ @Override
+ public String toString() {
+ return mName;
+ }
+
+ public String getUUIDString() {
+ return mUuid.toString();
+ }
+
+ public PrivateKey getKeystoreKey() {
+ return mPrivateKey;
+ }
+
+ public String getSignedData(String b64data) {
+ PrivateKey privkey = getKeystoreKey();
+ Exception err = null;
+
+ byte[] data = Base64.decode(b64data, Base64.DEFAULT);
+
+ // The Jelly Bean *evil* Hack
+ // 4.2 implements the RSA/ECB/PKCS1PADDING in the OpenSSLprovider
+ if (Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN) {
+ return processSignJellyBeans(privkey, data);
+ }
+
+
+ try {
+
+
+ Cipher rsasinger = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
+
+ rsasinger.init(Cipher.ENCRYPT_MODE, privkey);
+
+ byte[] signed_bytes = rsasinger.doFinal(data);
+ return Base64.encodeToString(signed_bytes, Base64.NO_WRAP);
+
+ } catch (NoSuchAlgorithmException e) {
+ err = e;
+ } catch (InvalidKeyException e) {
+ err = e;
+ } catch (NoSuchPaddingException e) {
+ err = e;
+ } catch (IllegalBlockSizeException e) {
+ err = e;
+ } catch (BadPaddingException e) {
+ err = e;
+ }
+ if (err != null) {
+ OpenVPN.logError(R.string.error_rsa_sign, err.getClass().toString(), err.getLocalizedMessage());
+ }
+ return null;
+
+ }
+
+ private String processSignJellyBeans(PrivateKey privkey, byte[] data) {
+ Exception err = null;
+ try {
+ Method[] allm = privkey.getClass().getSuperclass().getDeclaredMethods();
+ System.out.println(allm);
+ Method getKey = privkey.getClass().getSuperclass().getDeclaredMethod("getOpenSSLKey");
+ getKey.setAccessible(true);
+
+ // Real object type is OpenSSLKey
+ Object opensslkey = getKey.invoke(privkey);
+
+ getKey.setAccessible(false);
+
+ Method getPkeyContext = opensslkey.getClass().getDeclaredMethod("getPkeyContext");
+
+ // integer pointer to EVP_pkey
+ getPkeyContext.setAccessible(true);
+ int pkey = (Integer) getPkeyContext.invoke(opensslkey);
+ getPkeyContext.setAccessible(false);
+
+ byte[] signed_bytes = NativeUtils.rsasign(data, pkey);
+ return Base64.encodeToString(signed_bytes, Base64.NO_WRAP);
+
+ } catch (NoSuchMethodException e) {
+ err = e;
+ } catch (IllegalArgumentException e) {
+ err = e;
+ } catch (IllegalAccessException e) {
+ err = e;
+ } catch (InvocationTargetException e) {
+ err = e;
+ } catch (InvalidKeyException e) {
+ err = e;
+ }
+ if (err != null) {
+ OpenVPN.logError(R.string.error_rsa_sign, err.getClass().toString(), err.getLocalizedMessage());
+ }
+ return null;
+
+ }
}