1 /*
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 
17 package com.android.internal.net;
18 
19 import android.app.PendingIntent;
20 import android.compat.annotation.UnsupportedAppUsage;
21 import android.content.ComponentName;
22 import android.content.Context;
23 import android.content.Intent;
24 import android.content.pm.PackageManager;
25 import android.content.pm.PackageManager.NameNotFoundException;
26 import android.content.pm.ResolveInfo;
27 import android.content.res.Resources;
28 import android.net.IpPrefix;
29 import android.net.LinkAddress;
30 import android.net.Network;
31 import android.net.ProxyInfo;
32 import android.net.RouteInfo;
33 import android.os.Parcel;
34 import android.os.Parcelable;
35 import android.os.UserHandle;
36 
37 import java.util.ArrayList;
38 import java.util.Arrays;
39 import java.util.List;
40 
41 /**
42  * A simple container used to carry information in VpnBuilder, VpnDialogs,
43  * and com.android.server.connectivity.Vpn. Internal use only.
44  *
45  * @hide
46  */
47 public class VpnConfig implements Parcelable {
48 
49     public static final String SERVICE_INTERFACE = "android.net.VpnService";
50 
51     public static final String DIALOGS_PACKAGE = "com.android.vpndialogs";
52 
53     // TODO: Rename this to something that encompasses Settings-based Platform VPNs as well.
54     public static final String LEGACY_VPN = "[Legacy VPN]";
55 
getIntentForConfirmation()56     public static Intent getIntentForConfirmation() {
57         Intent intent = new Intent();
58         ComponentName componentName = ComponentName.unflattenFromString(
59                 Resources.getSystem().getString(
60                         com.android.internal.R.string.config_customVpnConfirmDialogComponent));
61         intent.setClassName(componentName.getPackageName(), componentName.getClassName());
62         return intent;
63     }
64 
65     /** NOTE: This should only be used for legacy VPN. */
getIntentForStatusPanel(Context context)66     public static PendingIntent getIntentForStatusPanel(Context context) {
67         Intent intent = new Intent();
68         intent.setClassName(DIALOGS_PACKAGE, DIALOGS_PACKAGE + ".ManageDialog");
69         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_HISTORY |
70                 Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
71         return PendingIntent.getActivityAsUser(context, 0 /* requestCode */, intent,
72                 PendingIntent.FLAG_IMMUTABLE, null /* options */, UserHandle.CURRENT);
73     }
74 
getVpnLabel(Context context, String packageName)75     public static CharSequence getVpnLabel(Context context, String packageName)
76             throws NameNotFoundException {
77         PackageManager pm = context.getPackageManager();
78         Intent intent = new Intent(SERVICE_INTERFACE);
79         intent.setPackage(packageName);
80         List<ResolveInfo> services = pm.queryIntentServices(intent, 0 /* flags */);
81         if (services != null && services.size() == 1) {
82             // This app contains exactly one VPN service. Call loadLabel, which will attempt to
83             // load the service's label, and fall back to the app label if none is present.
84             return services.get(0).loadLabel(pm);
85         } else {
86             return pm.getApplicationInfo(packageName, 0).loadLabel(pm);
87         }
88     }
89 
90     public String user;
91     public String interfaze;
92     public String session;
93     public int mtu = -1;
94     public List<LinkAddress> addresses = new ArrayList<>();
95     public List<RouteInfo> routes = new ArrayList<>();
96     public List<String> dnsServers;
97     public List<String> searchDomains;
98     public List<String> allowedApplications;
99     public List<String> disallowedApplications;
100     public PendingIntent configureIntent;
101     public long startTime = -1;
102     public boolean legacy;
103     public boolean blocking;
104     public boolean allowBypass;
105     public boolean allowIPv4;
106     public boolean allowIPv6;
107     public boolean isMetered = true;
108     public boolean requiresInternetValidation = false;
109     public boolean excludeLocalRoutes = false;
110     public Network[] underlyingNetworks;
111     public ProxyInfo proxyInfo;
112 
113     @UnsupportedAppUsage
VpnConfig()114     public VpnConfig() {
115     }
116 
VpnConfig(VpnConfig other)117     public VpnConfig(VpnConfig other) {
118         user = other.user;
119         interfaze = other.interfaze;
120         session = other.session;
121         mtu = other.mtu;
122         addresses = copyOf(other.addresses);
123         routes = copyOf(other.routes);
124         dnsServers = copyOf(other.dnsServers);
125         searchDomains = copyOf(other.searchDomains);
126         allowedApplications = copyOf(other.allowedApplications);
127         disallowedApplications = copyOf(other.disallowedApplications);
128         configureIntent = other.configureIntent;
129         startTime = other.startTime;
130         legacy = other.legacy;
131         blocking = other.blocking;
132         allowBypass = other.allowBypass;
133         allowIPv4 = other.allowIPv4;
134         allowIPv6 = other.allowIPv6;
135         isMetered = other.isMetered;
136         requiresInternetValidation = other.requiresInternetValidation;
137         excludeLocalRoutes = other.excludeLocalRoutes;
138         underlyingNetworks = other.underlyingNetworks != null ? Arrays.copyOf(
139                 other.underlyingNetworks, other.underlyingNetworks.length) : null;
140         proxyInfo = other.proxyInfo;
141     }
142 
copyOf(List<T> list)143     private static <T> List<T> copyOf(List<T> list) {
144         return list != null ? new ArrayList<>(list) : null;
145     }
146 
addLegacyRoutes(String routesStr)147     public void addLegacyRoutes(String routesStr) {
148         if (routesStr.trim().equals("")) {
149             return;
150         }
151         String[] routes = routesStr.trim().split(" ");
152         for (String route : routes) {
153             //each route is ip/prefix
154             RouteInfo info = new RouteInfo(new IpPrefix(route), null, null, RouteInfo.RTN_UNICAST);
155             this.routes.add(info);
156         }
157     }
158 
addLegacyAddresses(String addressesStr)159     public void addLegacyAddresses(String addressesStr) {
160         if (addressesStr.trim().equals("")) {
161             return;
162         }
163         String[] addresses = addressesStr.trim().split(" ");
164         for (String address : addresses) {
165             //each address is ip/prefix
166             LinkAddress addr = new LinkAddress(address);
167             this.addresses.add(addr);
168         }
169     }
170 
171     @Override
describeContents()172     public int describeContents() {
173         return 0;
174     }
175 
176     @Override
writeToParcel(Parcel out, int flags)177     public void writeToParcel(Parcel out, int flags) {
178         out.writeString(user);
179         out.writeString(interfaze);
180         out.writeString(session);
181         out.writeInt(mtu);
182         out.writeTypedList(addresses);
183         out.writeTypedList(routes);
184         out.writeStringList(dnsServers);
185         out.writeStringList(searchDomains);
186         out.writeStringList(allowedApplications);
187         out.writeStringList(disallowedApplications);
188         out.writeParcelable(configureIntent, flags);
189         out.writeLong(startTime);
190         out.writeInt(legacy ? 1 : 0);
191         out.writeInt(blocking ? 1 : 0);
192         out.writeInt(allowBypass ? 1 : 0);
193         out.writeInt(allowIPv4 ? 1 : 0);
194         out.writeInt(allowIPv6 ? 1 : 0);
195         out.writeInt(isMetered ? 1 : 0);
196         out.writeInt(requiresInternetValidation ? 1 : 0);
197         out.writeInt(excludeLocalRoutes ? 1 : 0);
198         out.writeTypedArray(underlyingNetworks, flags);
199         out.writeParcelable(proxyInfo, flags);
200     }
201 
202     public static final Parcelable.Creator<VpnConfig> CREATOR =
203             new Parcelable.Creator<VpnConfig>() {
204         @Override
205         public VpnConfig createFromParcel(Parcel in) {
206             VpnConfig config = new VpnConfig();
207             config.user = in.readString();
208             config.interfaze = in.readString();
209             config.session = in.readString();
210             config.mtu = in.readInt();
211             in.readTypedList(config.addresses, LinkAddress.CREATOR);
212             in.readTypedList(config.routes, RouteInfo.CREATOR);
213             config.dnsServers = in.createStringArrayList();
214             config.searchDomains = in.createStringArrayList();
215             config.allowedApplications = in.createStringArrayList();
216             config.disallowedApplications = in.createStringArrayList();
217             config.configureIntent = in.readParcelable(null, android.app.PendingIntent.class);
218             config.startTime = in.readLong();
219             config.legacy = in.readInt() != 0;
220             config.blocking = in.readInt() != 0;
221             config.allowBypass = in.readInt() != 0;
222             config.allowIPv4 = in.readInt() != 0;
223             config.allowIPv6 = in.readInt() != 0;
224             config.isMetered = in.readInt() != 0;
225             config.requiresInternetValidation = in.readInt() != 0;
226             config.excludeLocalRoutes = in.readInt() != 0;
227             config.underlyingNetworks = in.createTypedArray(Network.CREATOR);
228             config.proxyInfo = in.readParcelable(null, android.net.ProxyInfo.class);
229             return config;
230         }
231 
232         @Override
233         public VpnConfig[] newArray(int size) {
234             return new VpnConfig[size];
235         }
236     };
237 
238     @Override
toString()239     public String toString() {
240         return new StringBuilder()
241                 .append("VpnConfig")
242                 .append("{ user=").append(user)
243                 .append(", interface=").append(interfaze)
244                 .append(", session=").append(session)
245                 .append(", mtu=").append(mtu)
246                 .append(", addresses=").append(toString(addresses))
247                 .append(", routes=").append(toString(routes))
248                 .append(", dns=").append(toString(dnsServers))
249                 .append(", searchDomains=").append(toString(searchDomains))
250                 .append(", allowedApps=").append(toString(allowedApplications))
251                 .append(", disallowedApps=").append(toString(disallowedApplications))
252                 .append(", configureIntent=").append(configureIntent)
253                 .append(", startTime=").append(startTime)
254                 .append(", legacy=").append(legacy)
255                 .append(", blocking=").append(blocking)
256                 .append(", allowBypass=").append(allowBypass)
257                 .append(", allowIPv4=").append(allowIPv4)
258                 .append(", allowIPv6=").append(allowIPv6)
259                 .append(", isMetered=").append(isMetered)
260                 .append(", requiresInternetValidation=").append(requiresInternetValidation)
261                 .append(", excludeLocalRoutes=").append(excludeLocalRoutes)
262                 .append(", underlyingNetworks=").append(Arrays.toString(underlyingNetworks))
263                 .append(", proxyInfo=").append(proxyInfo)
264                 .append("}")
265                 .toString();
266     }
267 
toString(List<T> ls)268     static <T> String toString(List<T> ls) {
269         if (ls == null) {
270             return "null";
271         }
272         return Arrays.toString(ls.toArray());
273     }
274 }
275