diff options
| -rw-r--r-- | res/layout/file_select.xml | 14 | ||||
| -rw-r--r-- | src/de/blinkt/openvpn/FileSelectLayout.java | 33 | ||||
| -rw-r--r-- | src/de/blinkt/openvpn/VpnProfile.java | 21 | ||||
| -rw-r--r-- | src/de/blinkt/openvpn/core/X509Utils.java | 78 | ||||
| -rw-r--r-- | src/de/blinkt/openvpn/fragments/Settings_Basic.java | 8 | ||||
| -rw-r--r-- | src/org/spongycastle/util/io/pem/PemReader.java | 84 | 
6 files changed, 205 insertions, 33 deletions
| diff --git a/res/layout/file_select.xml b/res/layout/file_select.xml index 0dd1abba..8c9e4da6 100644 --- a/res/layout/file_select.xml +++ b/res/layout/file_select.xml @@ -51,5 +51,17 @@          android:ellipsize="end"          android:singleLine="true"          android:text="@string/file_nothing_selected" /> -</RelativeLayout> +    <TextView +        android:id="@+id/file_selected_description" +        android:layout_width="wrap_content" +        android:textIsSelectable="true" +        android:layout_height="wrap_content" +        android:layout_alignParentLeft="true" +        android:layout_below="@+id/file_selected_item" +        android:layout_marginLeft="16dip" +        android:layout_toLeftOf="@+id/file_select_button" +        android:ellipsize="end" +        android:singleLine="true" /> + +</RelativeLayout>
\ No newline at end of file diff --git a/src/de/blinkt/openvpn/FileSelectLayout.java b/src/de/blinkt/openvpn/FileSelectLayout.java index b7e28b5c..d7bcc475 100644 --- a/src/de/blinkt/openvpn/FileSelectLayout.java +++ b/src/de/blinkt/openvpn/FileSelectLayout.java @@ -1,5 +1,6 @@  package de.blinkt.openvpn; +import de.blinkt.openvpn.core.X509Utils;  import android.app.Fragment;  import android.content.Context;  import android.content.Intent; @@ -22,19 +23,21 @@ public class FileSelectLayout extends LinearLayout implements OnClickListener {  	private boolean mBase64Encode;  	private String mTitle;  	private boolean mShowClear; +	private TextView mDataDetails;  	public FileSelectLayout( Context context,AttributeSet attrset) {  		super(context,attrset);  		inflate(getContext(), R.layout.file_select, this); -		 +  		TypedArray ta = context.obtainStyledAttributes(attrset,R.styleable.FileSelectLayout); -		 +  		mTitle = ta.getString(R.styleable.FileSelectLayout_title); -		 +  		TextView tview = (TextView) findViewById(R.id.file_title);  		tview.setText(mTitle); -		 +  		mDataView = (TextView) findViewById(R.id.file_selected_item); +		mDataDetails = (TextView) findViewById(R.id.file_selected_description);  		mSelectButton = (Button) findViewById(R.id.file_select_button);  		mSelectButton.setOnClickListener(this); @@ -46,7 +49,7 @@ public class FileSelectLayout extends LinearLayout implements OnClickListener {  		mTaskId = i;  		mFragment = fragment;  	} -	 +  	public void getCertificateFileDialog() {  		Intent startFC = new Intent(getContext(),FileSelect.class);  		startFC.putExtra(FileSelect.START_DATA, mData); @@ -58,20 +61,24 @@ public class FileSelectLayout extends LinearLayout implements OnClickListener {  		mFragment.startActivityForResult(startFC,mTaskId);  	} -	 +  	public String getData() {  		return mData;  	}  	public void setData(String data) {  		mData = data; -		if(data==null)  +		if(data==null) {   			mDataView.setText(mFragment.getString(R.string.no_data)); -		else if(mData.startsWith(VpnProfile.INLINE_TAG)) -			mDataView.setText(R.string.inline_file_data); -		else -			mDataView.setText(data); -		 +			mDataDetails.setText(""); +		}else { +			if(mData.startsWith(VpnProfile.INLINE_TAG)) +				mDataView.setText(R.string.inline_file_data); +			else +				mDataView.setText(data); +			mDataDetails.setText(X509Utils.getCertificateFriendlyName(data)); +		} +  	}  	@Override @@ -88,5 +95,5 @@ public class FileSelectLayout extends LinearLayout implements OnClickListener {  	public void setShowClear() {  		mShowClear=true;  	} -	 +  } diff --git a/src/de/blinkt/openvpn/VpnProfile.java b/src/de/blinkt/openvpn/VpnProfile.java index 9d183897..03fcbc1b 100644 --- a/src/de/blinkt/openvpn/VpnProfile.java +++ b/src/de/blinkt/openvpn/VpnProfile.java @@ -45,6 +45,7 @@ import de.blinkt.openvpn.R;  import de.blinkt.openvpn.core.NativeUtils;  import de.blinkt.openvpn.core.OpenVPN;  import de.blinkt.openvpn.core.OpenVpnService; +import de.blinkt.openvpn.core.X509Utils;  public class VpnProfile implements  Serializable{  	// Note that this class cannot be moved to core where it belongs since  @@ -52,7 +53,7 @@ public class VpnProfile implements  Serializable{  	// 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; @@ -79,7 +80,7 @@ public class VpnProfile implements  Serializable{  	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 @@ -590,7 +591,7 @@ public class VpnProfile implements  Serializable{  			if(nonNull(mCaFilename)) {  				try { -					Certificate cacert = getCacertFromFile(); +					Certificate cacert = X509Utils.getCertificateFromFile(mCaFilename);  					X509Certificate[] newcachain = new X509Certificate[cachain.length+1];  					for(int i=0;i<cachain.length;i++)  						newcachain[i]=cachain[i]; @@ -645,18 +646,6 @@ public class VpnProfile implements  Serializable{  		}  		return null;  	} -	private Certificate getCacertFromFile() throws FileNotFoundException, CertificateException { -		CertificateFactory certFact = CertificateFactory.getInstance("X.509"); - -		InputStream inStream; - -		if(mCaFilename.startsWith(INLINE_TAG)) -			inStream = new ByteArrayInputStream(mCaFilename.replace(INLINE_TAG,"").getBytes()); -		else  -			inStream = new FileInputStream(mCaFilename); - -		return certFact.generateCertificate(inStream); -	}  	//! Return an error if somethign is wrong @@ -681,6 +670,8 @@ public class VpnProfile implements  Serializable{  	} + +  	//! Openvpn asks for a "Private Key", this should be pkcs12 key  	//  	public String getPasswordPrivateKey() { diff --git a/src/de/blinkt/openvpn/core/X509Utils.java b/src/de/blinkt/openvpn/core/X509Utils.java new file mode 100644 index 00000000..e50343f4 --- /dev/null +++ b/src/de/blinkt/openvpn/core/X509Utils.java @@ -0,0 +1,78 @@ +package de.blinkt.openvpn.core; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.io.StringReader; +import java.security.KeyFactory; +import java.security.KeyPair; +import java.security.Principal; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; + +import javax.security.auth.x500.X500Principal; + +import org.spongycastle.util.io.pem.PemObject; +import org.spongycastle.util.io.pem.PemReader; + +import android.text.TextUtils; + +import de.blinkt.openvpn.VpnProfile; + +public class X509Utils { +	public static Certificate getCertificateFromFile(String certfilename) throws FileNotFoundException, CertificateException { +		CertificateFactory certFact = CertificateFactory.getInstance("X.509"); + +		InputStream inStream; + +		if(certfilename.startsWith(VpnProfile.INLINE_TAG)) +			inStream = new ByteArrayInputStream(certfilename.replace(VpnProfile.INLINE_TAG,"").getBytes()); +		else  +			inStream = new FileInputStream(certfilename); + +		return certFact.generateCertificate(inStream); +	} + +	public static PemObject readPemObjectFromFile (String keyfilename) throws CertificateException, IOException { + +		Reader inStream; + +		if(keyfilename.startsWith(VpnProfile.INLINE_TAG)) +			inStream = new StringReader(keyfilename.replace(VpnProfile.INLINE_TAG,"")); +		else  +			inStream = new FileReader(new File(keyfilename)); + +		PemReader pr = new PemReader(inStream); +		PemObject r = pr.readPemObject(); +		pr.close(); +		return r; +	} + + + + +	public static String getCertificateFriendlyName (String filename) { +		if(!TextUtils.isEmpty(filename)) { +			try { +				X509Certificate cert = (X509Certificate) getCertificateFromFile(filename); +				 +				String friendly = cert.getSubjectDN().getName(); +							 +				return friendly; + +			} catch (Exception e) { +				OpenVPN.logError("Could not read certificate" + e.getLocalizedMessage()); +			} +		} +		return "Could not read/parse certificate"; +	} + + +} diff --git a/src/de/blinkt/openvpn/fragments/Settings_Basic.java b/src/de/blinkt/openvpn/fragments/Settings_Basic.java index 7bcd302d..ad9a79ad 100644 --- a/src/de/blinkt/openvpn/fragments/Settings_Basic.java +++ b/src/de/blinkt/openvpn/fragments/Settings_Basic.java @@ -116,7 +116,7 @@ public class Settings_Basic extends Fragment implements View.OnClickListener, On  		return mView;  	} -	 +  	@Override  	public void onStart() {  		super.onStart(); @@ -138,7 +138,7 @@ public class Settings_Basic extends Fragment implements View.OnClickListener, On  			// Private key files may result in showing/hiding the private key password dialog  			if(fsl==mClientKey) {  				changeType(mType.getSelectedItemPosition()); -			} +			}   		}  	} @@ -183,13 +183,13 @@ public class Settings_Basic extends Fragment implements View.OnClickListener, On  			if(mProfile.requireTLSKeyPassword())  				mView.findViewById(R.id.key_password_layout).setVisibility(View.VISIBLE);  			break; -			 +  		case VpnProfile.TYPE_USERPASS_PKCS12:  			mView.findViewById(R.id.userpassword).setVisibility(View.VISIBLE);  		case VpnProfile.TYPE_PKCS12:  			mView.findViewById(R.id.pkcs12).setVisibility(View.VISIBLE);  			break; -			 +  		case VpnProfile.TYPE_STATICKEYS:  			mView.findViewById(R.id.statickeys).setVisibility(View.VISIBLE);  			break; diff --git a/src/org/spongycastle/util/io/pem/PemReader.java b/src/org/spongycastle/util/io/pem/PemReader.java new file mode 100644 index 00000000..cbbebab9 --- /dev/null +++ b/src/org/spongycastle/util/io/pem/PemReader.java @@ -0,0 +1,84 @@ +package org.spongycastle.util.io.pem; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.Reader; +import java.util.ArrayList; +import java.util.List; + +import org.spongycastle.util.encoders.Base64; + +public class PemReader +    extends BufferedReader +{ +    private static final String BEGIN = "-----BEGIN "; +    private static final String END = "-----END "; + +    public PemReader(Reader reader) +    { +        super(reader); +    } + +    public PemObject readPemObject() +        throws IOException +    { +        String line = readLine(); + +        while (line != null && !line.startsWith(BEGIN)) +        { +            line = readLine(); +        } + +        if (line != null) +        { +            line = line.substring(BEGIN.length()); +            int index = line.indexOf('-'); +            String type = line.substring(0, index); + +            if (index > 0) +            { +                return loadObject(type); +            } +        } + +        return null; +    } + +    private PemObject loadObject(String type) +        throws IOException +    { +        String          line; +        String          endMarker = END + type; +        StringBuffer    buf = new StringBuffer(); +        List            headers = new ArrayList(); + +        while ((line = readLine()) != null) +        { +            if (line.indexOf(":") >= 0) +            { +                int index = line.indexOf(':'); +                String hdr = line.substring(0, index); +                String value = line.substring(index + 1).trim(); + +                headers.add(new PemHeader(hdr, value)); + +                continue; +            } + +            if (line.indexOf(endMarker) != -1) +            { +                break; +            } +             +            buf.append(line.trim()); +        } + +        if (line == null) +        { +            throw new IOException(endMarker + " not found"); +        } + +        return new PemObject(type, headers, Base64.decode(buf.toString())); +    } + +} | 
