blob: a1f92cdf2170be5a333161423db0c3d7b7cc5d3f [file] [log] [blame]
Jeff Sharkey971a3cf2012-07-19 17:10:09 -07001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.internal.net;
18
Jeff Sharkey82f85212012-08-24 11:17:25 -070019import android.os.Parcel;
20import android.os.Parcelable;
Jeff Sharkey69ddab42012-08-25 00:05:46 -070021import android.text.TextUtils;
22import android.util.Log;
Jeff Sharkey82f85212012-08-24 11:17:25 -070023
Jeff Sharkey69ddab42012-08-25 00:05:46 -070024import java.net.InetAddress;
Elliott Hughesd396a442013-06-28 16:24:48 -070025import java.nio.charset.StandardCharsets;
Jeff Sharkey971a3cf2012-07-19 17:10:09 -070026
27/**
28 * Parcel-like entity class for VPN profiles. To keep things simple, all
29 * fields are package private. Methods are provided for serialization, so
30 * storage can be implemented easily. Two rules are set for this class.
31 * First, all fields must be kept non-null. Second, always make a copy
32 * using clone() before modifying.
33 *
34 * @hide
35 */
Jeff Sharkey82f85212012-08-24 11:17:25 -070036public class VpnProfile implements Cloneable, Parcelable {
Jeff Sharkey69ddab42012-08-25 00:05:46 -070037 private static final String TAG = "VpnProfile";
38
Jeff Sharkey971a3cf2012-07-19 17:10:09 -070039 // Match these constants with R.array.vpn_types.
40 public static final int TYPE_PPTP = 0;
41 public static final int TYPE_L2TP_IPSEC_PSK = 1;
42 public static final int TYPE_L2TP_IPSEC_RSA = 2;
43 public static final int TYPE_IPSEC_XAUTH_PSK = 3;
44 public static final int TYPE_IPSEC_XAUTH_RSA = 4;
45 public static final int TYPE_IPSEC_HYBRID_RSA = 5;
46 public static final int TYPE_MAX = 5;
47
48 // Entity fields.
49 public final String key; // -1
50 public String name = ""; // 0
51 public int type = TYPE_PPTP; // 1
52 public String server = ""; // 2
53 public String username = ""; // 3
54 public String password = ""; // 4
55 public String dnsServers = ""; // 5
56 public String searchDomains = ""; // 6
57 public String routes = ""; // 7
58 public boolean mppe = true; // 8
59 public String l2tpSecret = ""; // 9
60 public String ipsecIdentifier = "";// 10
61 public String ipsecSecret = ""; // 11
62 public String ipsecUserCert = ""; // 12
63 public String ipsecCaCert = ""; // 13
64 public String ipsecServerCert = "";// 14
65
66 // Helper fields.
67 public boolean saveLogin = false;
68
69 public VpnProfile(String key) {
70 this.key = key;
71 }
72
Jeff Sharkey6e7aa772012-10-19 10:48:11 -070073 public VpnProfile(Parcel in) {
74 key = in.readString();
75 name = in.readString();
76 type = in.readInt();
77 server = in.readString();
78 username = in.readString();
79 password = in.readString();
80 dnsServers = in.readString();
81 searchDomains = in.readString();
82 routes = in.readString();
83 mppe = in.readInt() != 0;
84 l2tpSecret = in.readString();
85 ipsecIdentifier = in.readString();
86 ipsecSecret = in.readString();
87 ipsecUserCert = in.readString();
88 ipsecCaCert = in.readString();
89 ipsecServerCert = in.readString();
90 saveLogin = in.readInt() != 0;
91 }
92
93 @Override
94 public void writeToParcel(Parcel out, int flags) {
95 out.writeString(key);
96 out.writeString(name);
97 out.writeInt(type);
98 out.writeString(server);
99 out.writeString(username);
100 out.writeString(password);
101 out.writeString(dnsServers);
102 out.writeString(searchDomains);
103 out.writeString(routes);
104 out.writeInt(mppe ? 1 : 0);
105 out.writeString(l2tpSecret);
106 out.writeString(ipsecIdentifier);
107 out.writeString(ipsecSecret);
108 out.writeString(ipsecUserCert);
109 out.writeString(ipsecCaCert);
110 out.writeString(ipsecServerCert);
111 out.writeInt(saveLogin ? 1 : 0);
112 }
113
Jeff Sharkey971a3cf2012-07-19 17:10:09 -0700114 public static VpnProfile decode(String key, byte[] value) {
115 try {
116 if (key == null) {
117 return null;
118 }
119
Elliott Hughesd396a442013-06-28 16:24:48 -0700120 String[] values = new String(value, StandardCharsets.UTF_8).split("\0", -1);
Jeff Sharkey971a3cf2012-07-19 17:10:09 -0700121 // There can be 14 or 15 values in ICS MR1.
122 if (values.length < 14 || values.length > 15) {
123 return null;
124 }
125
126 VpnProfile profile = new VpnProfile(key);
127 profile.name = values[0];
Narayan Kamatha09b4d22016-04-15 18:32:45 +0100128 profile.type = Integer.parseInt(values[1]);
Jeff Sharkey971a3cf2012-07-19 17:10:09 -0700129 if (profile.type < 0 || profile.type > TYPE_MAX) {
130 return null;
131 }
132 profile.server = values[2];
133 profile.username = values[3];
134 profile.password = values[4];
135 profile.dnsServers = values[5];
136 profile.searchDomains = values[6];
137 profile.routes = values[7];
Tobias Thiererb0800dc2016-04-21 17:51:41 +0100138 profile.mppe = Boolean.parseBoolean(values[8]);
Jeff Sharkey971a3cf2012-07-19 17:10:09 -0700139 profile.l2tpSecret = values[9];
140 profile.ipsecIdentifier = values[10];
141 profile.ipsecSecret = values[11];
142 profile.ipsecUserCert = values[12];
143 profile.ipsecCaCert = values[13];
144 profile.ipsecServerCert = (values.length > 14) ? values[14] : "";
145
146 profile.saveLogin = !profile.username.isEmpty() || !profile.password.isEmpty();
147 return profile;
148 } catch (Exception e) {
149 // ignore
150 }
151 return null;
152 }
153
154 public byte[] encode() {
155 StringBuilder builder = new StringBuilder(name);
156 builder.append('\0').append(type);
157 builder.append('\0').append(server);
158 builder.append('\0').append(saveLogin ? username : "");
159 builder.append('\0').append(saveLogin ? password : "");
160 builder.append('\0').append(dnsServers);
161 builder.append('\0').append(searchDomains);
162 builder.append('\0').append(routes);
163 builder.append('\0').append(mppe);
164 builder.append('\0').append(l2tpSecret);
165 builder.append('\0').append(ipsecIdentifier);
166 builder.append('\0').append(ipsecSecret);
167 builder.append('\0').append(ipsecUserCert);
168 builder.append('\0').append(ipsecCaCert);
169 builder.append('\0').append(ipsecServerCert);
Elliott Hughesd396a442013-06-28 16:24:48 -0700170 return builder.toString().getBytes(StandardCharsets.UTF_8);
Jeff Sharkey971a3cf2012-07-19 17:10:09 -0700171 }
Jeff Sharkey82f85212012-08-24 11:17:25 -0700172
Jeff Sharkey69ddab42012-08-25 00:05:46 -0700173 /**
174 * Test if profile is valid for lockdown, which requires IPv4 address for
175 * both server and DNS. Server hostnames would require using DNS before
176 * connection.
177 */
178 public boolean isValidLockdownProfile() {
179 try {
180 InetAddress.parseNumericAddress(server);
181
182 for (String dnsServer : dnsServers.split(" +")) {
183 InetAddress.parseNumericAddress(this.dnsServers);
184 }
185 if (TextUtils.isEmpty(dnsServers)) {
186 Log.w(TAG, "DNS required");
187 return false;
188 }
189
190 // Everything checked out above
191 return true;
192
193 } catch (IllegalArgumentException e) {
194 Log.w(TAG, "Invalid address", e);
195 return false;
196 }
197 }
198
Jeff Sharkey82f85212012-08-24 11:17:25 -0700199 public static final Creator<VpnProfile> CREATOR = new Creator<VpnProfile>() {
200 @Override
201 public VpnProfile createFromParcel(Parcel in) {
Jeff Sharkey6e7aa772012-10-19 10:48:11 -0700202 return new VpnProfile(in);
Jeff Sharkey82f85212012-08-24 11:17:25 -0700203 }
204
205 @Override
206 public VpnProfile[] newArray(int size) {
207 return new VpnProfile[size];
208 }
209 };
210
211 @Override
212 public int describeContents() {
213 return 0;
214 }
Jeff Sharkey971a3cf2012-07-19 17:10:09 -0700215}