diff options
author | Arne Schwabe <arne@rfc2549.org> | 2012-06-28 19:33:05 +0200 |
---|---|---|
committer | Arne Schwabe <arne@rfc2549.org> | 2012-06-28 19:33:05 +0200 |
commit | 73d3b9c032eae2074726cd3668546af1c44a8323 (patch) | |
tree | c40b4e6447efa6d1d1c8618a3f79723f29e2db14 /src/de | |
parent | 629417eb6b9db777b0db6b36d1c8ceb4c2760f7c (diff) |
The 'be ready for Jelly Beans' commit
- fix concurrentaccess occuring on JB
- JB does not allow to extract the private keys from the key storage, rewrite using the key storage to use JAVA API and the external-key management interface
Diffstat (limited to 'src/de')
-rw-r--r-- | src/de/blinkt/openvpn/ConfigConverter.java | 1 | ||||
-rw-r--r-- | src/de/blinkt/openvpn/FileSelect.java | 2 | ||||
-rw-r--r-- | src/de/blinkt/openvpn/OpenVPN.java | 6 | ||||
-rw-r--r-- | src/de/blinkt/openvpn/OpenVpnManagementThread.java | 40 | ||||
-rw-r--r-- | src/de/blinkt/openvpn/VpnProfile.java | 100 |
5 files changed, 99 insertions, 50 deletions
diff --git a/src/de/blinkt/openvpn/ConfigConverter.java b/src/de/blinkt/openvpn/ConfigConverter.java index 5e0a6eb3..3ccda053 100644 --- a/src/de/blinkt/openvpn/ConfigConverter.java +++ b/src/de/blinkt/openvpn/ConfigConverter.java @@ -134,6 +134,7 @@ public class ConfigConverter extends ListActivity { filedata += new String(buf,0,len);
len = fis.read(buf);
}
+ fis.close();
return filedata;
} catch (FileNotFoundException e) {
log(e.getLocalizedMessage());
diff --git a/src/de/blinkt/openvpn/FileSelect.java b/src/de/blinkt/openvpn/FileSelect.java index c235594e..bbad5cfd 100644 --- a/src/de/blinkt/openvpn/FileSelect.java +++ b/src/de/blinkt/openvpn/FileSelect.java @@ -113,7 +113,7 @@ public class FileSelect extends Activity { data += new String(buf,0,len); len=fis.read(buf); } - + fis.close(); mData =data; mInlineFragment.setData(data); getActionBar().selectTab(inlineFileTab); diff --git a/src/de/blinkt/openvpn/OpenVPN.java b/src/de/blinkt/openvpn/OpenVPN.java index 64ecf17c..db980200 100644 --- a/src/de/blinkt/openvpn/OpenVPN.java +++ b/src/de/blinkt/openvpn/OpenVPN.java @@ -147,7 +147,7 @@ public class OpenVPN { } - public static void updateStateString(String state, String msg) { + public synchronized static void updateStateString(String state, String msg) { for (StateListener sl : stateListener) { sl.updateState(state,msg); } @@ -179,7 +179,9 @@ public class OpenVPN { public static void logError(int ressourceId) { newlogItem(new LogItem(LogItem.ERROR, ressourceId)); } - + public static void logError(int ressourceId, Object... args) { + newlogItem(new LogItem(LogItem.ERROR, ressourceId,args)); + } } diff --git a/src/de/blinkt/openvpn/OpenVpnManagementThread.java b/src/de/blinkt/openvpn/OpenVpnManagementThread.java index f23d9d9b..e1b37342 100644 --- a/src/de/blinkt/openvpn/OpenVpnManagementThread.java +++ b/src/de/blinkt/openvpn/OpenVpnManagementThread.java @@ -5,11 +5,20 @@ import java.io.IOException; import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
import java.util.LinkedList;
import java.util.Vector;
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+
import android.net.LocalSocket;
import android.os.ParcelFileDescriptor;
+import android.util.Base64;
import android.util.Log;
public class OpenVpnManagementThread implements Runnable {
@@ -173,6 +182,8 @@ public class OpenVpnManagementThread implements Runnable { // 1 log level N,I,E etc.
// 2 log message
OpenVPN.logMessage(0, "", args[2]);
+ } else if (cmd.equals("RSA_SIGN")) {
+ processSignCommand(argument);
} else {
OpenVPN.logMessage(0, "MGMT:", "Got unrecognized command" + command);
Log.i(TAG, "Got unrecognized command" + command);
@@ -389,4 +400,33 @@ public class OpenVpnManagementThread implements Runnable { }
+ private void processSignCommand(String b64data) {
+ PrivateKey privkey = mProfile.getKeystoreKey();
+ Exception err =null;
+ try{
+ byte[] data = Base64.decode(b64data, Base64.DEFAULT);
+ Cipher rsasinger = javax.crypto.Cipher.getInstance("RSA/ECB/PKCS1PADDING");
+ rsasinger.init(Cipher.ENCRYPT_MODE, privkey);
+
+ byte[] signed_bytes = rsasinger.doFinal(data);
+ String signed_string = Base64.encodeToString(signed_bytes, Base64.NO_WRAP);
+ managmentCommand("rsa-sig\n");
+ managmentCommand(signed_string);
+ managmentCommand("\nEND\n");
+ } 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.getLocalizedMessage());
+ }
+ }
+
}
diff --git a/src/de/blinkt/openvpn/VpnProfile.java b/src/de/blinkt/openvpn/VpnProfile.java index dd729a06..8b758b3b 100644 --- a/src/de/blinkt/openvpn/VpnProfile.java +++ b/src/de/blinkt/openvpn/VpnProfile.java @@ -4,25 +4,23 @@ import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; -import java.io.FileOutputStream; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.Serializable; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.Collection; -import java.util.Random; import java.util.UUID; import java.util.Vector; +import org.spongycastle.util.io.pem.PemObject; +import org.spongycastle.util.io.pem.PemWriter; + import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; @@ -51,8 +49,7 @@ public class VpnProfile implements Serializable{ protected transient String mTransientPW=null; protected transient String mTransientPCKS12PW=null; - - private static transient String mTempPKCS12Password; + private transient PrivateKey mPrivateKey; public static String DEFAULT_DNS1="131.234.137.23"; public static String DEFAULT_DNS2="131.234.137.24"; @@ -100,6 +97,7 @@ public class VpnProfile implements Serializable{ public boolean mUseDefaultRoutev6=true; public String mCustomRoutesv6=""; public String mKeyPassword=""; + public void clearDefaults() { @@ -122,7 +120,8 @@ public class VpnProfile implements Serializable{ } - static final String OVPNCONFIGPKCS12 = "android.pkcs12"; + static final String OVPNCONFIGCA = "android-ca.pem"; + static final String OVPNCONFIGUSERCERT = "android-user.pem"; public VpnProfile(String name) { @@ -223,9 +222,10 @@ public class VpnProfile implements Serializable{ case VpnProfile.TYPE_USERPASS_KEYSTORE: cfg+="auth-user-pass\n"; case VpnProfile.TYPE_KEYSTORE: - cfg+="pkcs12 "; - cfg+=cacheDir.getAbsolutePath() + "/" + OVPNCONFIGPKCS12; - cfg+="\n"; + cfg+="ca " + cacheDir.getAbsolutePath() + "/" + OVPNCONFIGCA + "\n"; + cfg+="cert " + cacheDir.getAbsolutePath() + "/" + OVPNCONFIGUSERCERT + "\n"; + cfg+="management-external-key\n"; + break; case VpnProfile.TYPE_USERPASS: cfg+="auth-user-pass\n"; @@ -447,7 +447,7 @@ public class VpnProfile implements Serializable{ Intent intent = new Intent(context,OpenVpnService.class); if(mAuthenticationType == VpnProfile.TYPE_KEYSTORE || mAuthenticationType == VpnProfile.TYPE_USERPASS_KEYSTORE) { - savePKCS12(context); + saveCertificates(context); } intent.putExtra(prefix + ".ARGV" , buildOpenvpnArgv(context.getCacheDir())); @@ -468,27 +468,13 @@ public class VpnProfile implements Serializable{ return intent; } - private String getTemporaryPKCS12Password() { - if(mTempPKCS12Password!=null) - return mTempPKCS12Password; - - String pw= ""; - // Put enough digits togher to make a password :) - Random r = new Random(); - for(int i=0;i < 4;i++) { - pw += Integer.valueOf(r.nextInt(1000)).toString(); - } - - mTempPKCS12Password=pw; - return mTempPKCS12Password; - - } - - private void savePKCS12(Context context) { + private void saveCertificates(Context context) { PrivateKey privateKey = null; X509Certificate[] cachain=null; try { privateKey = KeyChain.getPrivateKey(context,mAlias); + mPrivateKey = privateKey; + cachain = KeyChain.getCertificateChain(context, mAlias); if(cachain.length <= 1 && !nonNull(mCaFilename)) OpenVPN.logMessage(0, "", context.getString(R.string.keychain_nocacert)); @@ -496,32 +482,50 @@ public class VpnProfile implements Serializable{ for(X509Certificate cert:cachain) { OpenVPN.logInfo(R.string.cert_from_keystore,cert.getSubjectDN()); } + + - KeyStore ks = KeyStore.getInstance("PKCS12"); - ks.load(null, null); + if(nonNull(mCaFilename)) { try { - Certificate cacert = getCacertFromFile(); - - ks.setCertificateEntry("cacert", cacert); + Certificate cacert = getCacertFromFile(); + X509Certificate[] newcachain = new X509Certificate[cachain.length+1]; + for(int i=0;i<cachain.length;i++) + newcachain[i]=cachain[i]; + + newcachain[cachain.length-1]=(X509Certificate) cacert; + } catch (Exception e) { OpenVPN.logError("Could not read CA certificate" + e.getLocalizedMessage()); } } - ks.setKeyEntry("usercert", privateKey, null, cachain); - String mypw = getTemporaryPKCS12Password(); - FileOutputStream fout = new FileOutputStream(context.getCacheDir().getAbsolutePath() + "/" + VpnProfile.OVPNCONFIGPKCS12); - ks.store(fout,mypw.toCharArray()); - fout.flush(); fout.close(); + + + FileWriter fout = new FileWriter(context.getCacheDir().getAbsolutePath() + "/" + VpnProfile.OVPNCONFIGCA); + PemWriter pw = new PemWriter(fout); + for(X509Certificate cert:cachain) { + pw.writeObject(new PemObject("CERTIFICATE", cert.getEncoded())); + } + + pw.close(); + + + if(cachain.length>= 1){ + X509Certificate usercert = cachain[0]; + + FileWriter userout = new FileWriter(context.getCacheDir().getAbsolutePath() + "/" + VpnProfile.OVPNCONFIGUSERCERT); + + PemWriter upw = new PemWriter(userout); + upw.writeObject(new PemObject("CERTIFICATE", usercert.getEncoded())); + upw.close(); + + } + return; } catch (InterruptedException e) { e.printStackTrace(); - } catch (KeyStoreException e) { - e.printStackTrace(); } catch (FileNotFoundException e) { e.printStackTrace(); - } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); } catch (CertificateException e) { e.printStackTrace(); } catch (IOException e) { @@ -574,10 +578,6 @@ public class VpnProfile implements Serializable{ return pwcopy; } switch (mAuthenticationType) { - case TYPE_KEYSTORE: - case TYPE_USERPASS_KEYSTORE: - return getTemporaryPKCS12Password(); - case TYPE_PKCS12: case TYPE_USERPASS_PKCS12: return mPKCS12Password; @@ -623,6 +623,7 @@ public class VpnProfile implements Serializable{ data += new String(buf,0,len); len = fr.read(buf); } + fr.close(); } catch (FileNotFoundException e) { return false; } catch (IOException e) { @@ -684,6 +685,11 @@ public class VpnProfile implements Serializable{ } + public PrivateKey getKeystoreKey() { + return mPrivateKey; + } + + } |