From: Jason Cooper <cyanogen at lakedaemon.net> Signed-off-by: Jason Cooper <cyanogen at lakedaemon.net> --- AndroidManifest.xml | 4 + res/values/strings.xml | 15 + res/xml/openconnect_advanced_settings.xml | 60 ++++ .../vpn/OpenconnectAuthenticationActor.java | 66 +++++ .../android/settings/vpn/OpenconnectEditor.java | 300 ++++++++++++++++++++ src/com/android/settings/vpn/VpnEditor.java | 4 + src/com/android/settings/vpn/VpnSettings.java | 8 + 7 files changed, 457 insertions(+), 0 deletions(-) create mode 100644 res/xml/openconnect_advanced_settings.xml create mode 100644 src/com/android/settings/vpn/OpenconnectAuthenticationActor.java create mode 100644 src/com/android/settings/vpn/OpenconnectEditor.java diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 2f303a4..b58dd56 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -218,6 +218,10 @@ <activity android:name=".vpn.OpenvpnEditor$AdvancedSettings" android:configChanges="orientation|keyboardHidden"> </activity> + <activity android:name=".vpn.OpenconnectEditor$AdvancedSettings" + android:configChanges="orientation|keyboardHidden"> + </activity> + <activity android:name="DateTimeSettings" android:label="@string/date_and_time" > diff --git a/res/values/strings.xml b/res/values/strings.xml index 0adefcf..257c374 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -2621,6 +2621,12 @@ found in the list of installed applications.</string> <string name="vpn_a_user_certificate">a user certificate</string> <!-- Preference title --> + <string name="vpn_server_certificate_title">Set server certificate</string> + <!-- Complete term --> + <string name="vpn_server_certificate">Server certificate</string> + <string name="vpn_a_server_certificate">a server certificate</string> + + <!-- Preference title --> <string name="vpn_ca_certificate_title">Set CA certificate</string> <!-- Complete term --> <string name="vpn_ca_certificate">Certificate authority (CA) certificate</string> @@ -2655,6 +2661,15 @@ found in the list of installed applications.</string> <string name="vpn_openvpn_set_extra">Extra arguments</string> <string name="vpn_openvpn_set_extra_message">Enter the extra command line arguments</string> + <string name="vpn_openconnect_port">Server port</string> + <string name="vpn_openconnect_userauth">User authentication</string> + <string name="vpn_openconnect_userauth_summary">Set if additional username/password authentication needs to be used</string> + <string name="vpn_openconnect_advanced_titlebar">Advanced OpenConnect Settings</string> + <string name="vpn_openconnect_comp_deflate">Deflate compression</string> + <string name="vpn_openconnect_comp_deflate_summary">Force Deflate compression to be set to on</string> + <string name="vpn_openconnect_set_extra">Extra arguments</string> + <string name="vpn_openconnect_set_extra_message">Enter the extra command line arguments</string> + <!-- Preference title --> <string name="vpn_ipsec_presharedkey_title">Set IPSec pre-shared key</string> <!-- Complete term --> diff --git a/res/xml/openconnect_advanced_settings.xml b/res/xml/openconnect_advanced_settings.xml new file mode 100644 index 0000000..89ee195 --- /dev/null +++ b/res/xml/openconnect_advanced_settings.xml @@ -0,0 +1,60 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2011 Jason Cooper <cyanogen at lakedaemon.net> + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<!-- copied from openvpn_advanced_settings.xml which was (same license): + + Copyright (C) 2010 James Bottomley <James.Bottomley at suse.de> + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" + android:title="@string/vpn_openconnect_advanced_titlebar"> + + <EditTextPreference + android:key="set_port" + android:title="@string/vpn_openconnect_port" + android:dialogTitle="@string/vpn_openconnect_port" + android:singleLine="true" + android:inputType="number" + /> + + <CheckBoxPreference + android:key="set_comp_deflate" + android:title="@string/vpn_openconnect_comp_deflate" + android:summary="@string/vpn_openconnect_comp_deflate_summary" + /> + + <EditTextPreference + android:key="set_extra" + android:title="@string/vpn_openconnect_set_extra" + android:dialogTitle="@string/vpn_openconnect_set_extra" + android:dialogMessage="@string/vpn_openconnect_set_extra_message" + android:singleLine="true" + android:inputType="text" + /> + +</PreferenceScreen> diff --git a/src/com/android/settings/vpn/OpenconnectAuthenticationActor.java b/src/com/android/settings/vpn/OpenconnectAuthenticationActor.java new file mode 100644 index 0000000..0e46c64 --- /dev/null +++ b/src/com/android/settings/vpn/OpenconnectAuthenticationActor.java @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2011 Jason Cooper <cyanogen at lakedaemon.net> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * copied from OpenvpnAuthenticationActor.java which was (same license): + * + * Copyright (C) 2010 James Bottomley <James.Bottomley at suse.de> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.vpn; + +import android.app.Dialog; +import android.content.Context; +import android.net.vpn.OpenconnectProfile; +import android.net.vpn.VpnProfile; + +/** + * A {@link VpnProfileActor} that provides an authentication view for users to + * input username and password before connecting to the VPN server. + */ +public class OpenconnectAuthenticationActor extends AuthenticationActor { + + OpenconnectAuthenticationActor(Context c, VpnProfile p) { + super(c, p); + } + + // @Override + public boolean isConnectDialogNeeded() { + OpenconnectProfile p = (OpenconnectProfile) getProfile(); + return p.getUserAuth(); + } + + public void connect(Dialog d) { + if (d == null) + // null d means we don't need an authentication dialogue + // so skip it and pass in null user and password + connect((String) null, (String) null); + else + super.connect(d); + } +} diff --git a/src/com/android/settings/vpn/OpenconnectEditor.java b/src/com/android/settings/vpn/OpenconnectEditor.java new file mode 100644 index 0000000..c4c619e --- /dev/null +++ b/src/com/android/settings/vpn/OpenconnectEditor.java @@ -0,0 +1,300 @@ +/* + * Copyright (C) 2011 Jason Cooper <cyanogen at lakedaemon.net> + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * copied from OpenvpnEditor.java which was (same license): + * + * Copyright (C) 2010 James Bottomley <James.Bottomley at suse.de> + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.vpn; + +import com.android.settings.R; + +import android.content.Context; +import android.content.Intent; +import android.net.vpn.OpenconnectProfile; +import android.os.Bundle; +import android.os.Parcelable; +import android.preference.CheckBoxPreference; +import android.preference.EditTextPreference; +import android.preference.ListPreference; +import android.preference.Preference; +import android.preference.PreferenceActivity; +import android.preference.PreferenceGroup; +import android.security.Credentials; +import android.security.KeyStore; +import android.util.Log; +import android.view.KeyEvent; +import android.view.Menu; +import android.view.MenuItem; + +/** + * The class for editing {@link OpenconnectProfile}. + */ +class OpenconnectEditor extends VpnProfileEditor { + + private static final String KEY_PROFILE = "openconnect_profile"; + + private static final int REQUEST_ADVANCED = 1; + + private static final String TAG = OpenconnectEditor.class.getSimpleName(); + + private int MENU_ID_ADVANCED; + + private KeyStore mKeyStore = KeyStore.getInstance(); + + private CheckBoxPreference mUserAuth; + + private ListPreference mCert; + + private ListPreference mSVRCert; + + private ListPreference mCACert; + + public OpenconnectEditor(OpenconnectProfile p) { + super(p); + } + + @Override + protected void loadExtraPreferencesTo(PreferenceGroup subpanel) { + final Context c = subpanel.getContext(); + final OpenconnectProfile profile = (OpenconnectProfile) getProfile(); + mUserAuth = new CheckBoxPreference(c); + mUserAuth.setTitle(R.string.vpn_openconnect_userauth); + mUserAuth.setSummary(R.string.vpn_openconnect_userauth_summary); + mUserAuth.setChecked(profile.getUserAuth()); + mUserAuth.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { + public boolean onPreferenceChange(Preference pref, Object newValue) { + boolean enabled = (Boolean) newValue; + profile.setUserAuth(enabled); + mUserAuth.setChecked(enabled); + return true; + } + }); + subpanel.addPreference(mUserAuth); + mCACert = createList(c, R.string.vpn_ca_certificate_title, profile.getCAName(), + mKeyStore.saw(Credentials.CA_CERTIFICATE), + new Preference.OnPreferenceChangeListener() { + public boolean onPreferenceChange(Preference pref, Object newValue) { + String f = (String) newValue; + profile.setCAName(f); + setSummary(mCACert, R.string.vpn_ca_certificate, profile.getCAName()); + + return true; + } + }); + setSummary(mCACert, R.string.vpn_ca_certificate, profile.getCAName()); + subpanel.addPreference(mCACert); + + mCert = createList(c, R.string.vpn_user_certificate_title, profile.getCertName(), + mKeyStore.saw(Credentials.USER_CERTIFICATE), + new Preference.OnPreferenceChangeListener() { + public boolean onPreferenceChange(Preference pref, Object newValue) { + String f = (String) newValue; + profile.setCertName(f); + setSummary(mCert, R.string.vpn_user_certificate, profile.getCertName()); + + return true; + } + }); + setSummary(mCert, R.string.vpn_user_certificate, profile.getCertName()); + subpanel.addPreference(mCert); + + mSVRCert = createList(c, R.string.vpn_server_certificate_title, profile.getSVRCertName(), + mKeyStore.saw(Credentials.USER_CERTIFICATE), + new Preference.OnPreferenceChangeListener() { + public boolean onPreferenceChange(Preference pref, Object newValue) { + String f = (String) newValue; + profile.setSVRCertName(f); + setSummary(mSVRCert, R.string.vpn_server_certificate, profile.getSVRCertName()); + + return true; + } + }); + setSummary(mSVRCert, R.string.vpn_server_certificate, profile.getSVRCertName()); + subpanel.addPreference(mSVRCert); + + } + + @Override + public String validate() { + String result = super.validate(); + if (result != null) + return result; + + if (!mUserAuth.isChecked()) { + result = validate(mCert, R.string.vpn_a_user_certificate); + if (result != null) + return result; + + result = validate(mCACert, R.string.vpn_a_ca_certificate); + if (result != null) + return result; + } + + result = validate(mSVRCert, R.string.vpn_a_server_certificate); + if (result != null) + return result; + + return null; + } + + @Override + protected void onCreateOptionsMenu(Menu menu, int last_item) { + MENU_ID_ADVANCED = last_item + 1; + + menu.add(0, MENU_ID_ADVANCED, 0, R.string.wifi_menu_advanced).setIcon( + android.R.drawable.ic_menu_manage); + } + + @Override + protected boolean onOptionsItemSelected(PreferenceActivity p, MenuItem item) { + if (item.getItemId() == MENU_ID_ADVANCED) { + Intent intent = new Intent(p, AdvancedSettings.class); + intent.putExtra(KEY_PROFILE, (Parcelable) getProfile()); + p.startActivityForResult(intent, REQUEST_ADVANCED); + return true; + } else { + return false; + } + } + + @Override + protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) { + if (requestCode != REQUEST_ADVANCED) + return; + + OpenconnectProfile p = (OpenconnectProfile) getProfile(); + OpenconnectProfile newP = data.getParcelableExtra(KEY_PROFILE); + if (newP == null) { + Log.e(TAG, "no profile from advanced settings"); + return; + } + // manually copy across all advanced settings + p.setPort(newP.getPort()); + p.setUseCompression(newP.getUseCompression()); + p.setExtra(newP.getExtra()); + } + + private ListPreference createList(Context c, int titleResId, String selection, String[] keys, + Preference.OnPreferenceChangeListener listener) { + ListPreference pref = new ListPreference(c); + pref.setTitle(titleResId); + pref.setDialogTitle(titleResId); + pref.setPersistent(true); + pref.setEntries(keys); + pref.setEntryValues(keys); + pref.setValue(selection); + pref.setOnPreferenceChangeListener(listener); + return pref; + } + + public static class AdvancedSettings extends PreferenceActivity { + private static final String KEY_PORT = "set_port"; + + private static final String KEY_COMP_DEFLATE = "set_comp_deflate"; + + private static final String KEY_EXTRA = "set_extra"; + + private EditTextPreference mPort; + + private CheckBoxPreference mCompression; + + private EditTextPreference mExtra; + + private OpenconnectProfile profile; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + profile = getIntent().getParcelableExtra(KEY_PROFILE); + + addPreferencesFromResource(R.xml.openconnect_advanced_settings); + + mPort = (EditTextPreference) findPreference(KEY_PORT); + mCompression = (CheckBoxPreference) findPreference(KEY_COMP_DEFLATE); + mExtra = (EditTextPreference) findPreference(KEY_EXTRA); + + mPort.setSummary(profile.getPort()); + mPort.setText(profile.getPort()); + mPort.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { + public boolean onPreferenceChange(Preference pref, Object newValue) { + String name = (String) newValue; + name.trim(); + profile.setPort(name); + mPort.setSummary(profile.getPort()); + + return true; + } + }); + + mCompression.setChecked(profile.getUseCompression()); + mCompression.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { + public boolean onPreferenceChange(Preference pref, Object newValue) { + Boolean b = (Boolean) newValue; + profile.setUseCompression(b); + + return true; + } + }); + + mExtra.setSummary(profile.getExtra()); + mExtra.setText(profile.getExtra()); + mExtra.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { + public boolean onPreferenceChange(Preference pref, Object newValue) { + String name = (String) newValue; + name.trim(); + profile.setExtra(name); + mExtra.setSummary(profile.getExtra()); + return true; + } + }); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + switch (keyCode) { + case KeyEvent.KEYCODE_BACK: + Intent intent = new Intent(this, VpnEditor.class); + intent.putExtra(KEY_PROFILE, (Parcelable) profile); + setResult(RESULT_OK, intent); + + finish(); + return true; + } + return super.onKeyDown(keyCode, event); + } + + } +} diff --git a/src/com/android/settings/vpn/VpnEditor.java b/src/com/android/settings/vpn/VpnEditor.java index 9f4730b..95b3027 100644 --- a/src/com/android/settings/vpn/VpnEditor.java +++ b/src/com/android/settings/vpn/VpnEditor.java @@ -26,6 +26,7 @@ import android.net.vpn.L2tpIpsecProfile; import android.net.vpn.L2tpIpsecPskProfile; import android.net.vpn.L2tpProfile; import android.net.vpn.OpenvpnProfile; +import android.net.vpn.OpenconnectProfile; import android.net.vpn.PptpProfile; import android.net.vpn.VpnProfile; import android.net.vpn.VpnType; @@ -187,6 +188,9 @@ public class VpnEditor extends PreferenceActivity { case OPENVPN: return new OpenvpnEditor((OpenvpnProfile) p); + case OPENCONNECT: + return new OpenconnectEditor((OpenconnectProfile) p); + case PPTP: return new PptpEditor((PptpProfile) p); diff --git a/src/com/android/settings/vpn/VpnSettings.java b/src/com/android/settings/vpn/VpnSettings.java index b9d549c..7540d21 100644 --- a/src/com/android/settings/vpn/VpnSettings.java +++ b/src/com/android/settings/vpn/VpnSettings.java @@ -626,6 +626,9 @@ public class VpnSettings extends PreferenceActivity implements case OPENVPN: return true; + case OPENCONNECT: + return true; + // pass through default: return false; @@ -640,6 +643,9 @@ public class VpnSettings extends PreferenceActivity implements case OPENVPN: return true; + case OPENCONNECT: + return true; + case L2TP: return ((L2tpProfile) p).isSecretEnabled(); @@ -875,6 +881,8 @@ public class VpnSettings extends PreferenceActivity implements switch (p.getType()) { case OPENVPN: return new OpenvpnAuthenticationActor(this, p); + case OPENCONNECT: + return new OpenconnectAuthenticationActor(this, p); default: return new AuthenticationActor(this, p); } -- 1.7.0.4