[PATCH] openconnect: add initial support for openconnect ssl vpn.
openconnect at lakedaemon.net
openconnect at lakedaemon.net
Thu Jul 14 21:38:54 EDT 2011
From: Jason Cooper <cyanogen at lakedaemon.net>
Signed-off-by: Jason Cooper <cyanogen at lakedaemon.net>
---
core/res/res/values/strings.xml | 1 +
.../com/android/server/vpn/OpenconnectService.java | 132 +++++++++++++++++
.../com/android/server/vpn/VpnServiceBinder.java | 6 +
vpn/java/android/net/vpn/OpenconnectProfile.java | 148 ++++++++++++++++++++
vpn/java/android/net/vpn/VpnType.java | 3 +-
5 files changed, 289 insertions(+), 1 deletions(-)
create mode 100644 packages/VpnServices/src/com/android/server/vpn/OpenconnectService.java
create mode 100644 vpn/java/android/net/vpn/OpenconnectProfile.java
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 967457d..b743825 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2358,6 +2358,7 @@
<string name="l2tp_ipsec_psk_vpn_description">Pre-shared key based L2TP/IPSec VPN</string>
<string name="l2tp_ipsec_crt_vpn_description">Certificate based L2TP/IPSec VPN</string>
<string name="openvpn_vpn_description">OpenVPN SSL VPN</string>
+ <string name="openconnect_vpn_description">OpenConnect SSL VPN</string>
<!-- Localized strings for WebView -->
<!-- Label for button in a WebView that will open a chooser to choose a file to upload -->
diff --git a/packages/VpnServices/src/com/android/server/vpn/OpenconnectService.java b/packages/VpnServices/src/com/android/server/vpn/OpenconnectService.java
new file mode 100644
index 0000000..e32a4c8
--- /dev/null
+++ b/packages/VpnServices/src/com/android/server/vpn/OpenconnectService.java
@@ -0,0 +1,132 @@
+/*
+ * 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 OpenvpnService.java which was (same license):
+ *
+ * Copyright (C) 2009, The Android Open Source Project
+ *
+ * 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.server.vpn;
+
+import android.net.LocalSocket;
+import android.net.LocalSocketAddress;
+import android.net.vpn.OpenconnectProfile;
+import android.net.vpn.VpnManager;
+import android.security.Credentials;
+import android.util.Log;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Scanner;
+
+/**
+ * The service that manages the openconnect VPN connection.
+ */
+class OpenconnectService extends VpnService<OpenconnectProfile> {
+
+ private static final String OPENCONNECT_DAEMON = "openconnect";
+
+ private static final String MTPD = "mtpd";
+
+ private static final String USE_INLINE = "[[INLINE]]";
+
+ private static final String USE_KEYSTORE = "[[ANDROID]]";
+
+ private static final String TAG = OpenconnectService.class.getSimpleName();
+
+ private static int count = 0;
+
+ private transient String mPassword;
+
+ private transient String mUsername;
+
+ private synchronized static String getCount() {
+ return Integer.toString(count++);
+ }
+
+ @Override
+ protected void connect(String serverIp, String username, String password) throws IOException {
+ OpenconnectProfile p = getProfile();
+ ArrayList<String> args = new ArrayList<String>();
+ String url = "https://" + p.getServerName() + ":" + p.getPort();
+
+ mUsername = username;
+ mPassword = password;
+
+ args.add(OPENCONNECT_DAEMON);
+
+ if (p.getCAName() != null) {
+ args.add("--cafile");
+ args.add(USE_INLINE);
+ args.add(USE_KEYSTORE + Credentials.CA_CERTIFICATE + p.getCAName());
+ }
+ if (p.getCertName() != null) {
+ args.add("--certificate");
+ args.add(USE_INLINE);
+ args.add(USE_KEYSTORE + Credentials.USER_CERTIFICATE + p.getCertName());
+ args.add("--sslkey");
+ args.add(USE_INLINE);
+ args.add(USE_KEYSTORE + Credentials.USER_PRIVATE_KEY + p.getCertName());
+ args.add("--key-type");
+ args.add("PKCS#12");
+ }
+ if (! p.getUseCompression()) {
+ args.add("--no-deflate");
+ }
+ if (p.getUserAuth()) {
+ args.add("-u");
+ args.add(mUsername);
+ args.add("--passwd-on-stdin");
+ args.add(mPassword);
+ }
+ if (p.getExtra() != null && !p.getExtra().equals("")) {
+ Scanner s = new Scanner(p.getExtra());
+ while (s.hasNext())
+ args.add(s.next());
+ }
+ args.add(url);
+ DaemonProxy mtpd = getDaemons().startDaemon(MTPD);
+ mtpd.sendCommand(args.toArray(new String[args.size()]));
+ }
+
+ @Override
+ void waitUntilConnectedOrTimedout() throws IOException {
+ setVpnStateUp(true);
+ }
+
+ void startConnectivityMonitor() {
+ /*
+ * Openconnect is completely event driven, so we don't need a polling
+ * monitor at all, so do nothing here
+ */
+ }
+
+}
diff --git a/packages/VpnServices/src/com/android/server/vpn/VpnServiceBinder.java b/packages/VpnServices/src/com/android/server/vpn/VpnServiceBinder.java
index 990da63..2c13a93 100644
--- a/packages/VpnServices/src/com/android/server/vpn/VpnServiceBinder.java
+++ b/packages/VpnServices/src/com/android/server/vpn/VpnServiceBinder.java
@@ -23,6 +23,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.VpnManager;
import android.net.vpn.VpnProfile;
@@ -168,6 +169,11 @@ public class VpnServiceBinder extends Service {
ovpn.setContext(this, (OpenvpnProfile)p );
return ovpn;
+ case OPENCONNECT:
+ OpenconnectService oconn = new OpenconnectService();
+ oconn.setContext(this, (OpenconnectProfile)p );
+ return oconn;
+
case PPTP:
PptpService pptp = new PptpService();
pptp.setContext(this, (PptpProfile) p);
diff --git a/vpn/java/android/net/vpn/OpenconnectProfile.java b/vpn/java/android/net/vpn/OpenconnectProfile.java
new file mode 100644
index 0000000..f544354
--- /dev/null
+++ b/vpn/java/android/net/vpn/OpenconnectProfile.java
@@ -0,0 +1,148 @@
+/*
+ * 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 OpenvpnProfile.java which was (same license):
+ *
+ * Copyright (C) 2009, The Android Open Source Project
+ *
+ * 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 android.net.vpn;
+
+import android.os.Parcel;
+
+/**
+ * The profile for OpenConnect type of VPN.
+ * {@hide}
+ */
+public class OpenconnectProfile extends VpnProfile {
+ private static final long serialVersionUID = 1L;
+
+ // Standard Settings
+ private boolean mUserAuth = true;
+
+ private String mCA;
+
+ private String mCert;
+
+ private String mSVRCert;
+
+ // Advanced Settings
+ private int mPort = 443;
+
+ private boolean mUseCompression = true;
+
+ private String mExtra;
+
+ @Override
+ public VpnType getType() {
+ return VpnType.OPENCONNECT;
+ }
+
+ public void setPort(String port) {
+ try {
+ mPort = Integer.parseInt(port);
+ } catch (NumberFormatException e) {
+ // no update
+ }
+ }
+
+ public String getPort() {
+ return Integer.toString(mPort);
+ }
+
+ public boolean getUserAuth() {
+ return mUserAuth;
+ }
+
+ public void setUserAuth(boolean auth) {
+ mUserAuth = auth;
+ }
+
+ public String getCAName() {
+ return mCA;
+ }
+
+ public void setCAName(String name) {
+ mCA = name;
+ }
+
+ public String getCertName() {
+ return mCert;
+ }
+
+ public void setCertName(String name) {
+ mCert = name;
+ }
+
+ public String getSVRCertName() {
+ return mSVRCert;
+ }
+
+ public void setSVRCertName(String name) {
+ mSVRCert = name;
+ }
+
+ public void setUseCompression(boolean b) {
+ mUseCompression = b;
+ }
+
+ public boolean getUseCompression() {
+ return mUseCompression;
+ }
+
+ public void setExtra(String extra) {
+ mExtra = extra;
+ }
+
+ public String getExtra() {
+ return mExtra;
+ }
+
+ @Override
+ protected void readFromParcel(Parcel in) {
+ super.readFromParcel(in);
+ mPort = in.readInt();
+ mCA = in.readString();
+ mCert = in.readString();
+ mSVRCert = in.readString();
+ mUseCompression = in.readInt() == 1;
+ mExtra = in.readString();
+ }
+
+ @Override
+ public void writeToParcel(Parcel parcel, int flags) {
+ super.writeToParcel(parcel, flags);
+ parcel.writeInt(mPort);
+ parcel.writeString(mCA);
+ parcel.writeString(mCert);
+ parcel.writeString(mSVRCert);
+ parcel.writeInt(mUseCompression ? 1 : 0);
+ parcel.writeString(mExtra);
+ }
+}
diff --git a/vpn/java/android/net/vpn/VpnType.java b/vpn/java/android/net/vpn/VpnType.java
index 2157067..a486318 100644
--- a/vpn/java/android/net/vpn/VpnType.java
+++ b/vpn/java/android/net/vpn/VpnType.java
@@ -29,7 +29,8 @@ public enum VpnType {
L2tpIpsecPskProfile.class),
L2TP_IPSEC("L2TP/IPSec CRT", R.string.l2tp_ipsec_crt_vpn_description,
L2tpIpsecProfile.class),
- OPENVPN("OpenVPN", R.string.openvpn_vpn_description, OpenvpnProfile.class);
+ OPENVPN("OpenVPN", R.string.openvpn_vpn_description, OpenvpnProfile.class),
+ OPENCONNECT("OpenConnect", R.string.openconnect_vpn_description, OpenconnectProfile.class);
private String mDisplayName;
private int mDescriptionId;
--
1.7.0.4
More information about the openconnect-devel
mailing list