diff options
| author | Arne Schwabe <arne@rfc2549.org> | 2014-02-11 23:36:48 +0100 | 
|---|---|---|
| committer | Arne Schwabe <arne@rfc2549.org> | 2014-02-11 23:36:48 +0100 | 
| commit | c373af42b1a75b0f23c2f0edbf196dfbb1ef0a0e (patch) | |
| tree | 1a6957889611f16974de15418ef0257e9f1ba90d | |
| parent | 3044e321058be2a7b860a7c10c8efa49afabfcb2 (diff) | |
Rework and fix config import
| -rwxr-xr-x | res/values/strings.xml | 1 | ||||
| -rw-r--r-- | src/de/blinkt/openvpn/VpnProfile.java | 34 | ||||
| -rw-r--r-- | src/de/blinkt/openvpn/activities/ConfigConverter.java | 749 | ||||
| -rw-r--r-- | src/de/blinkt/openvpn/activities/FileSelect.java | 6 | ||||
| -rw-r--r-- | src/de/blinkt/openvpn/core/ConfigParser.java | 28 | ||||
| -rw-r--r-- | src/de/blinkt/openvpn/core/X509Utils.java | 6 | ||||
| -rw-r--r-- | src/de/blinkt/openvpn/fragments/Settings_Authentication.java | 7 | ||||
| -rw-r--r-- | src/de/blinkt/openvpn/fragments/Utils.java | 67 | ||||
| -rw-r--r-- | src/de/blinkt/openvpn/views/FileSelectLayout.java | 10 | 
9 files changed, 503 insertions, 405 deletions
| diff --git a/res/values/strings.xml b/res/values/strings.xml index d96f51a0..f4f7f6eb 100755 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -314,4 +314,5 @@      <string name="blocklocal_summary">Networks directly connected to the local interfaces will not be routed over the VPN. Unchecking this option will redirect all traffic indented for local networks to VPN.</string>      <string name="blocklocal_title">Bypass VPN for local networks</string>      <string name="userpw_file">Username/Password file</string> +    <string name="imported_from_file">[Imported from: %s]</string>  </resources> diff --git a/src/de/blinkt/openvpn/VpnProfile.java b/src/de/blinkt/openvpn/VpnProfile.java index d18fc72a..1ec34b51 100644 --- a/src/de/blinkt/openvpn/VpnProfile.java +++ b/src/de/blinkt/openvpn/VpnProfile.java @@ -47,6 +47,7 @@ public class VpnProfile implements Serializable {      // 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 DISPLAYNAME_TAG = "[[NAME]]";      public static final String MINIVPN = "miniopenvpn";      private static final long serialVersionUID = 7085688938959334563L;      private static final String OVPNCONFIGFILE = "android.conf"; @@ -462,9 +463,9 @@ public class VpnProfile implements Serializable {          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 if (isEmbedded(filedata)) { +            String dataWithOutHeader = getEmbeddedContent(filedata); +            return String.format(Locale.ENGLISH, "<%s>\n%s\n</%s>\n", cfgentry, dataWithOutHeader, cfgentry);          } else {              return String.format(Locale.ENGLISH, "%s %s\n", cfgentry, openVpnEscape(filedata));          } @@ -583,6 +584,31 @@ public class VpnProfile implements Serializable {          return getKeyStoreCertificates(context, 5);      } +    public static String getDisplayName(String embeddedFile) { +        int start = DISPLAYNAME_TAG.length(); +        int end = embeddedFile.indexOf(INLINE_TAG); +        return embeddedFile.substring(start,end); +    } + +    public static String getEmbeddedContent(String data) +    { +        if (!data.contains(INLINE_TAG)) +            return data; + +        int start = data.indexOf(INLINE_TAG) + INLINE_TAG.length(); +        return data.substring(start); +    } + +    public static boolean isEmbedded(String data) { +        if (data==null) +            return false; +        if(data.startsWith(INLINE_TAG) || data.startsWith(DISPLAYNAME_TAG)) +            return true; +        else +            return false; +    } + +      class NoCertReturnedException extends Exception {          public NoCertReturnedException (String msg) {              super(msg); @@ -760,7 +786,7 @@ public class VpnProfile implements Serializable {              return false;          String data = ""; -        if (mClientKeyFilename.startsWith(INLINE_TAG)) +        if (isEmbedded(mClientKeyFilename))              data = mClientKeyFilename;          else {              char[] buf = new char[2048]; diff --git a/src/de/blinkt/openvpn/activities/ConfigConverter.java b/src/de/blinkt/openvpn/activities/ConfigConverter.java index 50253915..e999fe9f 100644 --- a/src/de/blinkt/openvpn/activities/ConfigConverter.java +++ b/src/de/blinkt/openvpn/activities/ConfigConverter.java @@ -1,24 +1,24 @@  package de.blinkt.openvpn.activities; -import java.io.*; -import java.util.*; -  import android.app.Activity;  import android.app.AlertDialog;  import android.app.AlertDialog.Builder;  import android.app.ListActivity;  import android.content.ActivityNotFoundException;  import android.content.Intent; +import android.database.Cursor;  import android.os.Bundle;  import android.os.Environment; +import android.provider.OpenableColumns;  import android.security.KeyChain;  import android.security.KeyChainAliasCallback; +import android.text.TextUtils;  import android.util.Base64; +import android.util.Log;  import android.view.*;  import android.widget.ArrayAdapter;  import android.widget.CheckBox; -  import android.widget.LinearLayout;  import de.blinkt.openvpn.R;  import de.blinkt.openvpn.VpnProfile; @@ -29,71 +29,75 @@ import de.blinkt.openvpn.fragments.Utils;  import de.blinkt.openvpn.views.FileSelectLayout;  import junit.framework.Assert; -import static de.blinkt.openvpn.views.FileSelectLayout.*; +import java.io.*; +import java.util.*; + +import static de.blinkt.openvpn.views.FileSelectLayout.FileSelectCallback;  public class ConfigConverter extends ListActivity implements FileSelectCallback { -	public static final String IMPORT_PROFILE = "de.blinkt.openvpn.IMPORT_PROFILE"; +    public static final String IMPORT_PROFILE = "de.blinkt.openvpn.IMPORT_PROFILE";      private static final int RESULT_INSTALLPKCS12 = 7;      private static final int CHOOSE_FILE_OFFSET = 1000;      public static final String VPNPROFILE = "vpnProfile";      private VpnProfile mResult; -	private transient ArrayAdapter<String> mArrayAdapter; +    private transient ArrayAdapter<String> mArrayAdapter; -	private transient List<String> mPathsegments; +    private transient List<String> mPathsegments; -	private String mAliasName=null; +    private String mAliasName = null;      private Map<Utils.FileType, FileSelectLayout> fileSelectMap = new HashMap<Utils.FileType, FileSelectLayout>(); +    private String mEmbeddedPwFile; -	@Override -	public boolean onOptionsItemSelected(MenuItem item) { -		if(item.getItemId()==R.id.cancel){ -			setResult(Activity.RESULT_CANCELED); -			finish(); -		} else if(item.getItemId()==R.id.ok) { -			if(mResult==null) { -				log("Importing the config had error, cannot save it"); -				return true; -			} +    @Override +    public boolean onOptionsItemSelected(MenuItem item) { +        if (item.getItemId() == R.id.cancel) { +            setResult(Activity.RESULT_CANCELED); +            finish(); +        } else if (item.getItemId() == R.id.ok) { +            if (mResult == null) { +                log("Importing the config had error, cannot save it"); +                return true; +            } -			Intent in = installPKCS12(); +            Intent in = installPKCS12(); -			if(in != null) -				startActivityForResult(in, RESULT_INSTALLPKCS12); -			else -				saveProfile(); +            if (in != null) +                startActivityForResult(in, RESULT_INSTALLPKCS12); +            else +                saveProfile(); -			return true; -		} +            return true; +        } -		return super.onOptionsItemSelected(item); +        return super.onOptionsItemSelected(item); -	} +    }      @Override      protected void onSaveInstanceState(Bundle outState) {          super.onSaveInstanceState(outState); -        if(mResult!=null) -            outState.putSerializable(VPNPROFILE,mResult); +        if (mResult != null) +            outState.putSerializable(VPNPROFILE, mResult);          outState.putString("mAliasName", mAliasName);          String[] logentries = new String[mArrayAdapter.getCount()]; -        for(int i =0; i < mArrayAdapter.getCount();i++){ +        for (int i = 0; i < mArrayAdapter.getCount(); i++) {              logentries[i] = mArrayAdapter.getItem(i);          }          outState.putStringArray("logentries", logentries);          int[] fileselects = new int[fileSelectMap.size()]; -        int k=0; -        for (Utils.FileType key :fileSelectMap.keySet()){ -            fileselects[k]=key.getValue(); +        int k = 0; +        for (Utils.FileType key : fileSelectMap.keySet()) { +            fileselects[k] = key.getValue();              k++;          } -        outState.putIntArray("fileselects",fileselects); - +        outState.putIntArray("fileselects", fileselects); +        outState.putString("pwfile",mEmbeddedPwFile);      }      @Override @@ -111,224 +115,222 @@ public class ConfigConverter extends ListActivity implements FileSelectCallback              String data = fs.getData(); -             switch (type){ -                 case USERPW_FILE: -                     ConfigParser.useEmbbedUserAuth(mResult, data); -                     break; -                 case PKCS12: -                     mResult.mPKCS12Filename = data; -                     break; -                 case TLS_AUTH_FILE: -                     mResult.mTLSAuthFilename = data; -                     break; -                 case CA_CERTIFICATE: -                     mResult.mCaFilename = data; -                     break; -                 case CLIENT_CERTIFICATE: -                     mResult.mClientCertFilename = data; -                     break; -                 case KEYFILE: -                     mResult.mClientKeyFilename = data; -                     break; -                 default: -                     Assert.fail(); -             } +            switch (type) { +                case USERPW_FILE: +                    mEmbeddedPwFile = data; +                    break; +                case PKCS12: +                    mResult.mPKCS12Filename = data; +                    break; +                case TLS_AUTH_FILE: +                    mResult.mTLSAuthFilename = data; +                    break; +                case CA_CERTIFICATE: +                    mResult.mCaFilename = data; +                    break; +                case CLIENT_CERTIFICATE: +                    mResult.mClientCertFilename = data; +                    break; +                case KEYFILE: +                    mResult.mClientKeyFilename = data; +                    break; +                default: +                    Assert.fail(); +            }          }          super.onActivityResult(requestCode, resultCode, result);      } -	private void saveProfile() { -		Intent result = new Intent(); -		ProfileManager vpl = ProfileManager.getInstance(this); +    private void saveProfile() { +        Intent result = new Intent(); +        ProfileManager vpl = ProfileManager.getInstance(this); +        if (!TextUtils.isEmpty(mEmbeddedPwFile)) +            ConfigParser.useEmbbedUserAuth(mResult, mEmbeddedPwFile); -		vpl.addProfile(mResult); -		vpl.saveProfile(this, mResult); -		vpl.saveProfileList(this); -		result.putExtra(VpnProfile.EXTRA_PROFILEUUID,mResult.getUUID().toString()); -		setResult(Activity.RESULT_OK, result); -		finish(); -	} +        vpl.addProfile(mResult); +        vpl.saveProfile(this, mResult); +        vpl.saveProfileList(this); +        result.putExtra(VpnProfile.EXTRA_PROFILEUUID, mResult.getUUID().toString()); +        setResult(Activity.RESULT_OK, result); +        finish(); +    } -	public void showCertDialog () { -		try	{ -			KeyChain.choosePrivateKeyAlias(this, -					new KeyChainAliasCallback() { +    public void showCertDialog() { +        try { +            KeyChain.choosePrivateKeyAlias(this, +                    new KeyChainAliasCallback() { -				public void alias(String alias) { -					// Credential alias selected.  Remember the alias selection for future use. -					mResult.mAlias=alias; -					saveProfile(); -				} +                        public void alias(String alias) { +                            // Credential alias selected.  Remember the alias selection for future use. +                            mResult.mAlias = alias; +                            saveProfile(); +                        } -			}, -			new String[] {"RSA"}, // List of acceptable key types. null for any -			null,                        // issuer, null for any -			mResult.mServerName,      // host name of server requesting the cert, null if unavailable -			-1,                         // port of server requesting the cert, -1 if unavailable -			mAliasName);                       // alias to preselect, null if unavailable -		} catch (ActivityNotFoundException anf) { -			Builder ab = new AlertDialog.Builder(this); -			ab.setTitle(R.string.broken_image_cert_title); -			ab.setMessage(R.string.broken_image_cert); -			ab.setPositiveButton(android.R.string.ok, null); -			ab.show(); -		} -	} +                    }, +                    new String[]{"RSA"}, // List of acceptable key types. null for any +                    null,                        // issuer, null for any +                    mResult.mServerName,      // host name of server requesting the cert, null if unavailable +                    -1,                         // port of server requesting the cert, -1 if unavailable +                    mAliasName);                       // alias to preselect, null if unavailable +        } catch (ActivityNotFoundException anf) { +            Builder ab = new AlertDialog.Builder(this); +            ab.setTitle(R.string.broken_image_cert_title); +            ab.setMessage(R.string.broken_image_cert); +            ab.setPositiveButton(android.R.string.ok, null); +            ab.show(); +        } +    } -	private Intent installPKCS12() { -		 -		if(!((CheckBox)findViewById(R.id.importpkcs12)).isChecked()) { -			setAuthTypeToEmbeddedPKCS12(); -			return null; -			 -		} -		String pkcs12datastr = mResult.mPKCS12Filename; -		if(pkcs12datastr!=null && pkcs12datastr.startsWith(VpnProfile.INLINE_TAG)) { -			Intent inkeyintent = KeyChain.createInstallIntent(); -			 -			pkcs12datastr= pkcs12datastr.substring(VpnProfile.INLINE_TAG.length()); -			 -			 -			byte[] pkcs12data = Base64.decode(pkcs12datastr, Base64.DEFAULT); +    private Intent installPKCS12() { +        if (!((CheckBox) findViewById(R.id.importpkcs12)).isChecked()) { +            setAuthTypeToEmbeddedPKCS12(); +            return null; -			inkeyintent.putExtra(KeyChain.EXTRA_PKCS12,pkcs12data ); +        } +        String pkcs12datastr = mResult.mPKCS12Filename; +        if (VpnProfile.isEmbedded(pkcs12datastr)) { +            Intent inkeyIntent = KeyChain.createInstallIntent(); -			if(mAliasName.equals("")) -				mAliasName=null; +            pkcs12datastr = VpnProfile.getEmbeddedContent(pkcs12datastr); -			if(mAliasName!=null){ -				inkeyintent.putExtra(KeyChain.EXTRA_NAME, mAliasName); -			} -			return inkeyintent; -		} -		return null; -	} +            byte[] pkcs12data = Base64.decode(pkcs12datastr, Base64.DEFAULT); +            inkeyIntent.putExtra(KeyChain.EXTRA_PKCS12, pkcs12data); -	private void setAuthTypeToEmbeddedPKCS12() { -		if(mResult.mPKCS12Filename!=null && mResult.mPKCS12Filename.startsWith(VpnProfile.INLINE_TAG)) { -			if(mResult.mAuthenticationType==VpnProfile.TYPE_USERPASS_KEYSTORE) -				mResult.mAuthenticationType=VpnProfile.TYPE_USERPASS_PKCS12; -			 -			if(mResult.mAuthenticationType==VpnProfile.TYPE_KEYSTORE) -				mResult.mAuthenticationType=VpnProfile.TYPE_PKCS12; -			 -		} -	} +            if (mAliasName.equals("")) +                mAliasName = null; +            if (mAliasName != null) { +                inkeyIntent.putExtra(KeyChain.EXTRA_NAME, mAliasName); +            } +            return inkeyIntent; +        } +        return null; +    } + + +    private void setAuthTypeToEmbeddedPKCS12() { +        if (VpnProfile.isEmbedded(mResult.mPKCS12Filename)) { +            if (mResult.mAuthenticationType == VpnProfile.TYPE_USERPASS_KEYSTORE) +                mResult.mAuthenticationType = VpnProfile.TYPE_USERPASS_PKCS12; +            if (mResult.mAuthenticationType == VpnProfile.TYPE_KEYSTORE) +                mResult.mAuthenticationType = VpnProfile.TYPE_PKCS12; + +        } +    } -	private String getUniqueProfileName(String possibleName) { +    private String getUniqueProfileName(String possibleName) { -		int i=0; +        int i = 0;          ProfileManager vpl = ProfileManager.getInstance(this); -		String newname = possibleName; - -		// 	Default to  -		if(mResult.mName!=null && !ConfigParser.CONVERTED_PROFILE.equals(mResult.mName)) -			newname=mResult.mName; -			 -		while(newname==null || vpl.getProfileByName(newname)!=null) { -			i++; -			if(i==1) -				newname = getString(R.string.converted_profile); -			else -				newname = getString(R.string.converted_profile_i,i); -		} - -		return newname; -	} - -	@Override -	public boolean onCreateOptionsMenu(Menu menu) { -		MenuInflater inflater = getMenuInflater(); -		inflater.inflate(R.menu.import_menu, menu); -		return true; -	} - -	private String embedFile(String filename, Utils.FileType type) -	{ -		if(filename==null) -			return null; - -		// Already embedded, nothing to do -		if(filename.startsWith(VpnProfile.INLINE_TAG)) -			return filename; - -		File possibleFile = findFile(filename, type); -		if(possibleFile==null) -			return filename; -		else -			return readFileContent(possibleFile,type == Utils.FileType.PKCS12); - -	} - -	private File findFile(String filename, Utils.FileType fileType) { -		File foundfile =findFileRaw(filename); -		 -		if (foundfile==null && filename!=null && !filename.equals("")) { -			log(R.string.import_could_not_open,filename); +        String newname = possibleName; + +        // 	Default to +        if (mResult.mName != null && !ConfigParser.CONVERTED_PROFILE.equals(mResult.mName)) +            newname = mResult.mName; + +        while (newname == null || vpl.getProfileByName(newname) != null) { +            i++; +            if (i == 1) +                newname = getString(R.string.converted_profile); +            else +                newname = getString(R.string.converted_profile_i, i); +        } + +        return newname; +    } + +    @Override +    public boolean onCreateOptionsMenu(Menu menu) { +        MenuInflater inflater = getMenuInflater(); +        inflater.inflate(R.menu.import_menu, menu); +        return true; +    } + +    private String embedFile(String filename, Utils.FileType type) { +        if (filename == null) +            return null; + +        // Already embedded, nothing to do +        if (VpnProfile.isEmbedded(filename)) +            return filename; + +        File possibleFile = findFile(filename, type); +        if (possibleFile == null) +            return filename; +        else +            return readFileContent(possibleFile, type == Utils.FileType.PKCS12); + +    } + +    private File findFile(String filename, Utils.FileType fileType) { +        File foundfile = findFileRaw(filename); + +        if (foundfile == null && filename != null && !filename.equals("")) { +            log(R.string.import_could_not_open, filename);              addFileSelectDialog(fileType);          } -		return foundfile; -	} +        return foundfile; +    }      private void addFileSelectDialog(Utils.FileType type) {          int titleRes = 0; -        String value=null; +        String value = null;          switch (type) {              case KEYFILE:                  titleRes = R.string.client_key_title; -                if (mResult!=null) +                if (mResult != null)                      value = mResult.mClientKeyFilename;                  break;              case CLIENT_CERTIFICATE:                  titleRes = R.string.client_certificate_title; -                if (mResult!=null) +                if (mResult != null)                      value = mResult.mClientCertFilename;                  break;              case CA_CERTIFICATE:                  titleRes = R.string.ca_title; -                if (mResult!=null) +                if (mResult != null)                      value = mResult.mCaFilename;                  break;              case TLS_AUTH_FILE:                  titleRes = R.string.tls_auth_file; -                if (mResult!=null) +                if (mResult != null)                      value = mResult.mTLSAuthFilename;                  break;              case PKCS12:                  titleRes = R.string.client_pkcs12_title; -                if (mResult!=null) +                if (mResult != null)                      value = mResult.mPKCS12Filename;                  break;              case USERPW_FILE:                  titleRes = R.string.userpw_file; -                return; +                value = mEmbeddedPwFile; +                break;          }          boolean isCert = type == Utils.FileType.CA_CERTIFICATE || type == Utils.FileType.CLIENT_CERTIFICATE; -        FileSelectLayout fl = new FileSelectLayout(this,getString(titleRes), isCert); +        FileSelectLayout fl = new FileSelectLayout(this, getString(titleRes), isCert);          fileSelectMap.put(type, fl);          fl.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));          ((LinearLayout) findViewById(R.id.config_convert_root)).addView(fl, 1); -        fl.setData(value,this); +        fl.setData(value, this);          int i = getFileLayoutOffset(type);          fl.setCaller(this, i, type); @@ -339,132 +341,127 @@ public class ConfigConverter extends ListActivity implements FileSelectCallback      } -    private File findFileRaw(String filename) -	{ -		if(filename == null || filename.equals("")) -			return null; +    private File findFileRaw(String filename) { +        if (filename == null || filename.equals("")) +            return null; -		// Try diffent path relative to /mnt/sdcard -		File sdcard = Environment.getExternalStorageDirectory(); -		File root = new File("/"); +        // Try diffent path relative to /mnt/sdcard +        File sdcard = Environment.getExternalStorageDirectory(); +        File root = new File("/"); -		HashSet<File> dirlist = new HashSet<File>(); +        HashSet<File> dirlist = new HashSet<File>(); -		for(int i=mPathsegments.size()-1;i >=0 ;i--){ -			String path = ""; -			for (int j = 0;j<=i;j++) { -				path += "/" + mPathsegments.get(j); -			} +        for (int i = mPathsegments.size() - 1; i >= 0; i--) { +            String path = ""; +            for (int j = 0; j <= i; j++) { +                path += "/" + mPathsegments.get(j); +            }              // Do a little hackish dance for the Android File Importer              // /document/primary:ovpn/openvpn-imt.conf -            if (path.indexOf(':')!=-1) { -                String possibleDir = path.substring(path.indexOf(':')+1,path.length()); -                possibleDir = possibleDir.substring(0,possibleDir.lastIndexOf('/')); +            if (path.indexOf(':') != -1) { +                String possibleDir = path.substring(path.indexOf(':') + 1, path.length()); +                possibleDir = possibleDir.substring(0, possibleDir.lastIndexOf('/')); + + +                dirlist.add(new File(sdcard, possibleDir)); + +            } +            dirlist.add(new File(path)); + + +        } +        dirlist.add(sdcard); +        dirlist.add(root); + + +        String[] fileparts = filename.split("/"); +        for (File rootdir : dirlist) { +            String suffix = ""; +            for (int i = fileparts.length - 1; i >= 0; i--) { +                if (i == fileparts.length - 1) +                    suffix = fileparts[i]; +                else +                    suffix = fileparts[i] + "/" + suffix; +                File possibleFile = new File(rootdir, suffix); +                if (!possibleFile.canRead()) +                    continue; -                dirlist.add(new File(sdcard,possibleDir)); +                // read the file inline +                return possibleFile;              } -			dirlist.add(new File(path)); - - -		} -		dirlist.add(sdcard); -		dirlist.add(root); - - -		String[] fileparts = filename.split("/"); -		for(File rootdir:dirlist){ -			String suffix=""; -			for(int i=fileparts.length-1; i >=0;i--) { -				if(i==fileparts.length-1) -					suffix = fileparts[i]; -				else -					suffix = fileparts[i] + "/" + suffix; - -				File possibleFile = new File(rootdir,suffix); -				if(!possibleFile.canRead()) -					continue; - -				// read the file inline -				return possibleFile; - -			} -		} -		return null; -	} - -	String readFileContent(File possibleFile, boolean base64encode) { -		byte [] filedata; -		try { -			filedata = readBytesFromFile(possibleFile); -		} catch (IOException e) { -			log(e.getLocalizedMessage()); -			return null; -		} -		 -		String data; -		if(base64encode) { -			data = Base64.encodeToString(filedata, Base64.DEFAULT); -		} else { -			data = new String(filedata); - -		} -		return VpnProfile.INLINE_TAG + data; -		 -	} - - -	private byte[] readBytesFromFile(File file) throws IOException { -		InputStream input = new FileInputStream(file); - -		long len= file.length(); +        } +        return null; +    } + +    String readFileContent(File possibleFile, boolean base64encode) { +        byte[] filedata; +        try { +            filedata = readBytesFromFile(possibleFile); +        } catch (IOException e) { +            log(e.getLocalizedMessage()); +            return null; +        } + +        String data; +        if (base64encode) { +            data = Base64.encodeToString(filedata, Base64.DEFAULT); +        } else { +            data = new String(filedata); + +        } + +        return VpnProfile.DISPLAYNAME_TAG + possibleFile.getName() + VpnProfile.INLINE_TAG + data; + +    } + + +    private byte[] readBytesFromFile(File file) throws IOException { +        InputStream input = new FileInputStream(file); + +        long len = file.length();          if (len > VpnProfile.MAX_EMBED_FILE_SIZE)              throw new IOException("File size of file to import too large."); -		// Create the byte array to hold the data -		byte[] bytes = new byte[(int) len]; - -		// Read in the bytes -		int offset = 0; -		int bytesRead = 0; -		while (offset < bytes.length -				&& (bytesRead=input.read(bytes, offset, bytes.length-offset)) >= 0) { -			offset += bytesRead; -		} - -		input.close(); -		return bytes; -	} - -	void embedFiles() { -		// This where I would like to have a c++ style -		// void embedFile(std::string & option) - -		if (mResult.mPKCS12Filename!=null) { -			File pkcs12file = findFileRaw(mResult.mPKCS12Filename); -			if(pkcs12file!=null) { -				mAliasName = pkcs12file.getName().replace(".p12", ""); -			} else { -				mAliasName = "Imported PKCS12"; -			} -		} -			 -		 -		mResult.mCaFilename = embedFile(mResult.mCaFilename, Utils.FileType.CA_CERTIFICATE); -		mResult.mClientCertFilename = embedFile(mResult.mClientCertFilename, Utils.FileType.CLIENT_CERTIFICATE); -		mResult.mClientKeyFilename = embedFile(mResult.mClientKeyFilename, Utils.FileType.KEYFILE); -		mResult.mTLSAuthFilename = embedFile(mResult.mTLSAuthFilename, Utils.FileType.TLS_AUTH_FILE); -		mResult.mPKCS12Filename = embedFile(mResult.mPKCS12Filename, Utils.FileType.PKCS12); -		 - -		if(mResult.mUsername == null && mResult.mPassword != null ){ -			String data =embedFile(mResult.mPassword, Utils.FileType.USERPW_FILE); -            ConfigParser.useEmbbedUserAuth(mResult, data); +        // Create the byte array to hold the data +        byte[] bytes = new byte[(int) len]; + +        // Read in the bytes +        int offset = 0; +        int bytesRead = 0; +        while (offset < bytes.length +                && (bytesRead = input.read(bytes, offset, bytes.length - offset)) >= 0) { +            offset += bytesRead; +        } + +        input.close(); +        return bytes; +    } + +    void embedFiles() { +        // This where I would like to have a c++ style +        // void embedFile(std::string & option) + +        if (mResult.mPKCS12Filename != null) { +            File pkcs12file = findFileRaw(mResult.mPKCS12Filename); +            if (pkcs12file != null) { +                mAliasName = pkcs12file.getName().replace(".p12", ""); +            } else { +                mAliasName = "Imported PKCS12"; +            }          } -	} + + +        mResult.mCaFilename = embedFile(mResult.mCaFilename, Utils.FileType.CA_CERTIFICATE); +        mResult.mClientCertFilename = embedFile(mResult.mClientCertFilename, Utils.FileType.CLIENT_CERTIFICATE); +        mResult.mClientKeyFilename = embedFile(mResult.mClientKeyFilename, Utils.FileType.KEYFILE); +        mResult.mTLSAuthFilename = embedFile(mResult.mTLSAuthFilename, Utils.FileType.TLS_AUTH_FILE); +        mResult.mPKCS12Filename = embedFile(mResult.mPKCS12Filename, Utils.FileType.PKCS12); +        mEmbeddedPwFile = embedFile(mResult.mPassword, Utils.FileType.USERPW_FILE); +    }      @Override      protected void onCreate(Bundle savedInstanceState) { @@ -477,11 +474,12 @@ public class ConfigConverter extends ListActivity implements FileSelectCallback          super.onCreate(savedInstanceState); -        if (savedInstanceState !=null && savedInstanceState.containsKey(VPNPROFILE)) { +        if (savedInstanceState != null && savedInstanceState.containsKey(VPNPROFILE)) {              mResult = (VpnProfile) savedInstanceState.getSerializable(VPNPROFILE);              mAliasName = savedInstanceState.getString("mAliasName"); +            mEmbeddedPwFile = savedInstanceState.getString("pwfile");              mArrayAdapter.addAll(savedInstanceState.getStringArray("logentries")); -            for (int k: savedInstanceState.getIntArray("fileselects")) { +            for (int k : savedInstanceState.getIntArray("fileselects")) {                  addFileSelectDialog(Utils.FileType.getFileTypeByValue(k));              } @@ -489,34 +487,52 @@ public class ConfigConverter extends ListActivity implements FileSelectCallback          } +        final android.content.Intent intent = getIntent(); -        final android.content.Intent intent = getIntent (); - -        if (intent != null ) -        { -            final android.net.Uri data = intent.getData (); -            if (data != null) -            { +        if (intent != null) { +            final android.net.Uri data = intent.getData(); +            if (data != null) {                  //log(R.string.import_experimental); -                log(R.string.importing_config,data.toString()); +                log(R.string.importing_config, data.toString());                  try {                      String possibleName = null; -                    if(data.getScheme().equals("file") || +                    if (data.getScheme().equals("file") ||                              data.getLastPathSegment().endsWith(".ovpn") || -                            data.getLastPathSegment().endsWith(".conf")) -                    { +                            data.getLastPathSegment().endsWith(".conf")) {                          possibleName = data.getLastPathSegment(); -                        if (possibleName.lastIndexOf('/')!=-1) -                            possibleName = possibleName.substring(possibleName.lastIndexOf('/')+1); +                        if (possibleName.lastIndexOf('/') != -1) +                            possibleName = possibleName.substring(possibleName.lastIndexOf('/') + 1); -                        if(possibleName!=null){ -                            possibleName =possibleName.replace(".ovpn", ""); -                            possibleName =possibleName.replace(".conf", ""); -                        }                      }                      InputStream is = getContentResolver().openInputStream(data);                      mPathsegments = data.getPathSegments(); + +                    Cursor cursor = getContentResolver().query(data, null, null, null, null); +                    try { + + +                        if (cursor.moveToFirst()) { +                            int cidx = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME); + +                            if (cidx != -1) { +                                String displayName = cursor.getString(cidx); +                                if (displayName != null) +                                    possibleName = displayName; +                            } +                            cidx = cursor.getColumnIndex("mime_type"); +                            if (cidx != -1) { +                                log("Opening Mime TYPE: " + cursor.getString(cidx)); +                            } +                        } +                    } finally { +                        cursor.close(); +                    } +                    if (possibleName != null) { +                        possibleName = possibleName.replace(".ovpn", ""); +                        possibleName = possibleName.replace(".conf", ""); +                    } +                      doImport(is, possibleName);                  } catch (FileNotFoundException e) { @@ -532,66 +548,65 @@ public class ConfigConverter extends ListActivity implements FileSelectCallback      } -	@Override -	protected void onStart() { -		super.onStart(); - +    @Override +    protected void onStart() { +        super.onStart(); -	} +    } -	private void log(String logmessage) { -		mArrayAdapter.add(logmessage); -	} +    private void log(String logmessage) { +        mArrayAdapter.add(logmessage); +    } -	private void doImport(InputStream is, String newName) { -		ConfigParser cp = new ConfigParser(); -		try { -			InputStreamReader isr = new InputStreamReader(is); +    private void doImport(InputStream is, String newName) { +        ConfigParser cp = new ConfigParser(); +        try { +            InputStreamReader isr = new InputStreamReader(is); -			cp.parseConfig(isr); -			VpnProfile vp = cp.convertProfile(); -			mResult = vp; -			embedFiles(); -			displayWarnings(); +            cp.parseConfig(isr); +            VpnProfile vp = cp.convertProfile(); +            mResult = vp; +            embedFiles(); +            displayWarnings();              mResult.mName = getUniqueProfileName(newName);              log(R.string.import_done); -			return; - -		} catch (IOException e) { -			log(R.string.error_reading_config_file); -			log(e.getLocalizedMessage()); -		} catch (ConfigParseError e) { -			log(R.string.error_reading_config_file); -			log(e.getLocalizedMessage());			 -		} -		mResult=null; - -	} - -	private void displayWarnings() { -		if(mResult.mUseCustomConfig) { -			log(R.string.import_warning_custom_options); -			String copt = mResult.mCustomConfigOptions; -			if(copt.startsWith("#")) { -				int until = copt.indexOf('\n'); -				copt = copt.substring(until+1); -			} - -			log(copt); -		} - -		if(mResult.mAuthenticationType==VpnProfile.TYPE_KEYSTORE || -				mResult.mAuthenticationType == VpnProfile.TYPE_USERPASS_KEYSTORE) { -			findViewById(R.id.importpkcs12).setVisibility(View.VISIBLE); -		} - -	} - -	private void log(int ressourceId, Object... formatArgs) { -		log(getString(ressourceId,formatArgs)); -	} +            return; + +        } catch (IOException e) { +            log(R.string.error_reading_config_file); +            log(e.getLocalizedMessage()); +        } catch (ConfigParseError e) { +            log(R.string.error_reading_config_file); +            log(e.getLocalizedMessage()); +        } +        mResult = null; + +    } + +    private void displayWarnings() { +        if (mResult.mUseCustomConfig) { +            log(R.string.import_warning_custom_options); +            String copt = mResult.mCustomConfigOptions; +            if (copt.startsWith("#")) { +                int until = copt.indexOf('\n'); +                copt = copt.substring(until + 1); +            } + +            log(copt); +        } + +        if (mResult.mAuthenticationType == VpnProfile.TYPE_KEYSTORE || +                mResult.mAuthenticationType == VpnProfile.TYPE_USERPASS_KEYSTORE) { +            findViewById(R.id.importpkcs12).setVisibility(View.VISIBLE); +        } + +    } + +    private void log(int ressourceId, Object... formatArgs) { +        log(getString(ressourceId, formatArgs)); +    }  } diff --git a/src/de/blinkt/openvpn/activities/FileSelect.java b/src/de/blinkt/openvpn/activities/FileSelect.java index 50584063..8967b1bf 100644 --- a/src/de/blinkt/openvpn/activities/FileSelect.java +++ b/src/de/blinkt/openvpn/activities/FileSelect.java @@ -185,15 +185,15 @@ public class FileSelect extends Activity {  	}  	public String getSelectPath() { -		if(!mData.startsWith(VpnProfile.INLINE_TAG)) +		if(VpnProfile.isEmbedded(mData))  			return mData;  		else  			return Environment.getExternalStorageDirectory().getPath();  	}  	public CharSequence getInlineData() { -		if(mData.startsWith(VpnProfile.INLINE_TAG)) -			return mData.substring(VpnProfile.INLINE_TAG.length()); +		if(VpnProfile.isEmbedded(mData)) +			return VpnProfile.getEmbeddedContent(mData);  		else  			return "";  	} diff --git a/src/de/blinkt/openvpn/core/ConfigParser.java b/src/de/blinkt/openvpn/core/ConfigParser.java index 06acdf98..22cc5dce 100644 --- a/src/de/blinkt/openvpn/core/ConfigParser.java +++ b/src/de/blinkt/openvpn/core/ConfigParser.java @@ -398,10 +398,18 @@ public class ConfigParser {  		if(direction!=null)  			np.mTLSAuthDirection=direction.get(1); +        Vector<Vector<String>> defgw = getAllOption("redirect-gateway", 0, 5); +		if(defgw != null) +        { +            np.mUseDefaultRoute=true; +            checkRedirectParameters(np, defgw); +        } -		if(getAllOption("redirect-gateway", 0, 5) != null) -			np.mUseDefaultRoute=true; - +        Vector<Vector<String>> redirectPrivate = getAllOption("redirect-private",0,5); +        if (redirectPrivate != null) +        { +            checkRedirectParameters(np,redirectPrivate); +        }  		Vector<String> dev =getOption("dev",1,1);  		Vector<String> devtype =getOption("dev-type",1,1); @@ -621,7 +629,17 @@ public class ConfigParser {  		return np;  	} -	public void useExtraRemotesAsCustom(boolean b) { +    private void checkRedirectParameters(VpnProfile np, Vector<Vector<String>> defgw) { +        for (Vector<String> redirect: defgw) +            for (int i=1;i<redirect.size();i++){ +                if (defgw.get(i).equals("block-local")) +                    np.mAllowLocalLAN=false; +                else if (defgw.get(i).equals("unblock-local")) +                    np.mAllowLocalLAN=true; +            } +    } + +    public void useExtraRemotesAsCustom(boolean b) {  		this.extraRemotesAsCustom = b;  	} @@ -641,7 +659,7 @@ public class ConfigParser {  	static public void useEmbbedUserAuth(VpnProfile np,String inlinedata)  	{ -		String data = inlinedata.replace(VpnProfile.INLINE_TAG, ""); +		String data = VpnProfile.getEmbeddedContent(inlinedata);  		String[] parts = data.split("\n");  		if(parts.length >= 2) {  			np.mUsername=parts[0]; diff --git a/src/de/blinkt/openvpn/core/X509Utils.java b/src/de/blinkt/openvpn/core/X509Utils.java index 5781cbf5..da1e4ed5 100644 --- a/src/de/blinkt/openvpn/core/X509Utils.java +++ b/src/de/blinkt/openvpn/core/X509Utils.java @@ -25,7 +25,7 @@ public class X509Utils {  		InputStream inStream; -		if(certfilename.startsWith(VpnProfile.INLINE_TAG)) { +		if(VpnProfile.isEmbedded(certfilename)) {              // The java certifcate reader is ... kind of stupid              // It does NOT ignore chars before the --BEGIN ...              int subIndex = certfilename.indexOf("-----BEGIN CERTIFICATE-----"); @@ -45,8 +45,8 @@ public class X509Utils {  		Reader inStream; -		if(keyfilename.startsWith(VpnProfile.INLINE_TAG)) -			inStream = new StringReader(keyfilename.replace(VpnProfile.INLINE_TAG,"")); +		if(VpnProfile.isEmbedded(keyfilename)) +			inStream = new StringReader(VpnProfile.getEmbeddedContent(keyfilename));  		else   			inStream = new FileReader(new File(keyfilename)); diff --git a/src/de/blinkt/openvpn/fragments/Settings_Authentication.java b/src/de/blinkt/openvpn/fragments/Settings_Authentication.java index b153ce4d..236d7947 100644 --- a/src/de/blinkt/openvpn/fragments/Settings_Authentication.java +++ b/src/de/blinkt/openvpn/fragments/Settings_Authentication.java @@ -191,7 +191,7 @@ public class Settings_Authentication extends OpenVpnPreferencesFragment implemen  			setTlsAuthSummary(result);  		}  else if (requestCode == SELECT_TLS_FILE_KITKAT && resultCode == Activity.RESULT_OK) {              try { -                mTlsAuthFileData= VpnProfile.INLINE_TAG + Utils.getStringFromFilePickerResult(Utils.FileType.TLS_AUTH_FILE,data,getActivity()); +                mTlsAuthFileData= Utils.getFilePickerResult(Utils.FileType.TLS_AUTH_FILE,data,getActivity());                  setTlsAuthSummary(mTlsAuthFileData);              } catch (IOException e) {                  VpnStatus.logException(e); @@ -200,9 +200,12 @@ public class Settings_Authentication extends OpenVpnPreferencesFragment implemen  	}  	private void setTlsAuthSummary(String result) { -		if(result==null) result = getString(R.string.no_certificate); +		if(result==null) +            result = getString(R.string.no_certificate);  		if(result.startsWith(VpnProfile.INLINE_TAG))  			mTLSAuthFile.setSummary(R.string.inline_file_data); +        else if (result.startsWith(VpnProfile.DISPLAYNAME_TAG)) +            mExpectTLSCert.setSummary(getString(R.string.imported_from_file, VpnProfile.getDisplayName(result)));  		else  			mTLSAuthFile.setSummary(result);  	} diff --git a/src/de/blinkt/openvpn/fragments/Utils.java b/src/de/blinkt/openvpn/fragments/Utils.java index f13b1987..6f06f35a 100644 --- a/src/de/blinkt/openvpn/fragments/Utils.java +++ b/src/de/blinkt/openvpn/fragments/Utils.java @@ -3,10 +3,14 @@ package de.blinkt.openvpn.fragments;  import android.annotation.TargetApi;  import android.content.Context;  import android.content.Intent; +import android.database.Cursor;  import android.net.Uri;  import android.os.Build; +import android.provider.OpenableColumns;  import android.util.Base64; +import android.util.Log;  import android.webkit.MimeTypeMap; +import de.blinkt.openvpn.VpnProfile;  import junit.framework.Assert;  import java.io.*; @@ -44,6 +48,21 @@ public class Utils {                  i.setType("application/x-pem-file");                  supportedMimeTypes.add("application/x-pem-file");                  supportedMimeTypes.add("application/pkcs8"); + +                // Google drive .... +                supportedMimeTypes.add("application/x-iwork-keynote-sffkey"); +                extensions.add("key"); +                break; + +            case TLS_AUTH_FILE: +                i.setType("text/plain"); + +                // Backup .... +                supportedMimeTypes.add("application/pkcs8"); +                // Google Drive is kind of crazy ..... +                supportedMimeTypes.add("application/x-iwork-keynote-sffkey"); + +                extensions.add("txt");                  extensions.add("key");                  break; @@ -52,19 +71,14 @@ public class Utils {                  supportedMimeTypes.add("application/x-openvpn-profile");                  supportedMimeTypes.add("application/openvpn-profile");                  supportedMimeTypes.add("application/ovpn"); +                supportedMimeTypes.add("text/plain");                  extensions.add("ovpn");                  extensions.add("conf");                  break; -            case TLS_AUTH_FILE: -                i.setType("text/plain"); -                // Backup .... -                supportedMimeTypes.add("application/pkcs8"); -                extensions.add("txt"); -                extensions.add("key"); -                break;              case USERPW_FILE: -                Assert.fail(); +                i.setType("text/plain"); +                supportedMimeTypes.add("text/plain");                  break;          } @@ -74,10 +88,11 @@ public class Utils {              String mimeType = mtm.getMimeTypeFromExtension(ext);              if (mimeType != null)                  supportedMimeTypes.add(mimeType); -            else -                supportedMimeTypes.add("application/octet-stream");          } +        // Always add this as fallback +        supportedMimeTypes.add("application/octet-stream"); +          i.putExtra(Intent.EXTRA_MIME_TYPES, supportedMimeTypes.toArray(new String[supportedMimeTypes.size()]));          return i;      } @@ -94,12 +109,11 @@ public class Utils {          private int value;          FileType(int i) { -            value=i; +            value = i;          } -        public static FileType getFileTypeByValue(int value) -        { -            switch(value) { +        public static FileType getFileTypeByValue(int value) { +            switch (value) {                  case 0:                      return PKCS12;                  case 1: @@ -140,14 +154,32 @@ public class Utils {          return buffer.toByteArray();      } -    public static String getStringFromFilePickerResult(FileType ft, Intent result, Context c) throws IOException { +    public static String getFilePickerResult(FileType ft, Intent result, Context c) throws IOException {          Uri uri = result.getData(); -        if (uri ==null) +        if (uri == null)              return null;          byte[] fileData = readBytesFromStream(c.getContentResolver().openInputStream(uri));          String newData = null; + +        Cursor cursor = c.getContentResolver().query(uri, null, null, null, null); + +        String prefix = ""; +        try { +            if (cursor.moveToFirst()) { +                int cidx = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME); +                if (cidx != -1) { +                    String displayName = cursor.getString(cidx); + +                    if (!displayName.contains(VpnProfile.INLINE_TAG) && !displayName.contains(VpnProfile.DISPLAYNAME_TAG)) +                        prefix = VpnProfile.DISPLAYNAME_TAG + displayName; +                } +            } +        } finally { +            cursor.close(); +        } +          switch (ft) {              case PKCS12:                  newData = Base64.encodeToString(fileData, Base64.DEFAULT); @@ -156,6 +188,7 @@ public class Utils {                  newData = new String(fileData, "UTF-8");                  break;          } -        return newData; + +        return prefix + VpnProfile.INLINE_TAG + newData;      }  } diff --git a/src/de/blinkt/openvpn/views/FileSelectLayout.java b/src/de/blinkt/openvpn/views/FileSelectLayout.java index 04392b47..362777e4 100644 --- a/src/de/blinkt/openvpn/views/FileSelectLayout.java +++ b/src/de/blinkt/openvpn/views/FileSelectLayout.java @@ -29,9 +29,9 @@ public class FileSelectLayout extends LinearLayout implements OnClickListener {              setData(fileData, c);          } else if (data != null) {              try { -                String newData = Utils.getStringFromFilePickerResult(fileType,data,c); +                String newData = Utils.getFilePickerResult(fileType, data, c);                  if (newData!=null) -                    setData(VpnProfile.INLINE_TAG + newData, c); +                    setData(newData, c);              } catch (IOException e) {                  VpnStatus.logException(e); @@ -119,10 +119,12 @@ public class FileSelectLayout extends LinearLayout implements OnClickListener {      public void setData(String data, Context c) {          mData = data;          if (data == null) { -            mDataView.setText(mFragment.getString(R.string.no_data)); +            mDataView.setText(c.getString(R.string.no_data));              mDataDetails.setText("");          } else { -            if (mData.startsWith(VpnProfile.INLINE_TAG)) +            if (mData.startsWith(VpnProfile.DISPLAYNAME_TAG)) { +                mDataView.setText(c.getString(R.string.imported_from_file, VpnProfile.getDisplayName(mData))); +            } else if (mData.startsWith(VpnProfile.INLINE_TAG))                  mDataView.setText(R.string.inline_file_data);              else                  mDataView.setText(data); | 
