[PATCH] openconnect: add initial support for openconnect ssl vpn.
openconnect at lakedaemon.net
openconnect at lakedaemon.net
Thu Jul 14 21:38:56 EDT 2011
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
More information about the openconnect-devel
mailing list