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