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.annotation.UnsupportedAppUsage;
20 import android.app.PendingIntent;
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     public static final String LEGACY_VPN = "[Legacy VPN]";
56 
getIntentForConfirmation()57     public static Intent getIntentForConfirmation() {
58         Intent intent = new Intent();
59         ComponentName componentName = ComponentName.unflattenFromString(
60                 Resources.getSystem().getString(
61                         com.android.internal.R.string.config_customVpnConfirmDialogComponent));
62         intent.setClassName(componentName.getPackageName(), componentName.getClassName());
63         return intent;
64     }
65 
66     /** NOTE: This should only be used for legacy VPN. */
getIntentForStatusPanel(Context context)67     public static PendingIntent getIntentForStatusPanel(Context context) {
68         Intent intent = new Intent();
69         intent.setClassName(DIALOGS_PACKAGE, DIALOGS_PACKAGE + ".ManageDialog");
70         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_HISTORY |
71                 Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
72         return PendingIntent.getActivityAsUser(context, 0, intent, 0, null, 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<LinkAddress>();
95     public List<RouteInfo> routes = new ArrayList<RouteInfo>();
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 Network[] underlyingNetworks;
109     public ProxyInfo proxyInfo;
110 
updateAllowedFamilies(InetAddress address)111     public void updateAllowedFamilies(InetAddress address) {
112         if (address instanceof Inet4Address) {
113             allowIPv4 = true;
114         } else {
115             allowIPv6 = true;
116         }
117     }
118 
addLegacyRoutes(String routesStr)119     public void addLegacyRoutes(String routesStr) {
120         if (routesStr.trim().equals("")) {
121             return;
122         }
123         String[] routes = routesStr.trim().split(" ");
124         for (String route : routes) {
125             //each route is ip/prefix
126             RouteInfo info = new RouteInfo(new IpPrefix(route), null);
127             this.routes.add(info);
128             updateAllowedFamilies(info.getDestination().getAddress());
129         }
130     }
131 
addLegacyAddresses(String addressesStr)132     public void addLegacyAddresses(String addressesStr) {
133         if (addressesStr.trim().equals("")) {
134             return;
135         }
136         String[] addresses = addressesStr.trim().split(" ");
137         for (String address : addresses) {
138             //each address is ip/prefix
139             LinkAddress addr = new LinkAddress(address);
140             this.addresses.add(addr);
141             updateAllowedFamilies(addr.getAddress());
142         }
143     }
144 
145     @Override
describeContents()146     public int describeContents() {
147         return 0;
148     }
149 
150     @Override
writeToParcel(Parcel out, int flags)151     public void writeToParcel(Parcel out, int flags) {
152         out.writeString(user);
153         out.writeString(interfaze);
154         out.writeString(session);
155         out.writeInt(mtu);
156         out.writeTypedList(addresses);
157         out.writeTypedList(routes);
158         out.writeStringList(dnsServers);
159         out.writeStringList(searchDomains);
160         out.writeStringList(allowedApplications);
161         out.writeStringList(disallowedApplications);
162         out.writeParcelable(configureIntent, flags);
163         out.writeLong(startTime);
164         out.writeInt(legacy ? 1 : 0);
165         out.writeInt(blocking ? 1 : 0);
166         out.writeInt(allowBypass ? 1 : 0);
167         out.writeInt(allowIPv4 ? 1 : 0);
168         out.writeInt(allowIPv6 ? 1 : 0);
169         out.writeInt(isMetered ? 1 : 0);
170         out.writeTypedArray(underlyingNetworks, flags);
171         out.writeParcelable(proxyInfo, flags);
172     }
173 
174     public static final Parcelable.Creator<VpnConfig> CREATOR =
175             new Parcelable.Creator<VpnConfig>() {
176         @Override
177         public VpnConfig createFromParcel(Parcel in) {
178             VpnConfig config = new VpnConfig();
179             config.user = in.readString();
180             config.interfaze = in.readString();
181             config.session = in.readString();
182             config.mtu = in.readInt();
183             in.readTypedList(config.addresses, LinkAddress.CREATOR);
184             in.readTypedList(config.routes, RouteInfo.CREATOR);
185             config.dnsServers = in.createStringArrayList();
186             config.searchDomains = in.createStringArrayList();
187             config.allowedApplications = in.createStringArrayList();
188             config.disallowedApplications = in.createStringArrayList();
189             config.configureIntent = in.readParcelable(null);
190             config.startTime = in.readLong();
191             config.legacy = in.readInt() != 0;
192             config.blocking = in.readInt() != 0;
193             config.allowBypass = in.readInt() != 0;
194             config.allowIPv4 = in.readInt() != 0;
195             config.allowIPv6 = in.readInt() != 0;
196             config.isMetered = in.readInt() != 0;
197             config.underlyingNetworks = in.createTypedArray(Network.CREATOR);
198             config.proxyInfo = in.readParcelable(null);
199             return config;
200         }
201 
202         @Override
203         public VpnConfig[] newArray(int size) {
204             return new VpnConfig[size];
205         }
206     };
207 
208     @Override
toString()209     public String toString() {
210         return new StringBuilder()
211                 .append("VpnConfig")
212                 .append("{ user=").append(user)
213                 .append(", interface=").append(interfaze)
214                 .append(", session=").append(session)
215                 .append(", mtu=").append(mtu)
216                 .append(", addresses=").append(toString(addresses))
217                 .append(", routes=").append(toString(routes))
218                 .append(", dns=").append(toString(dnsServers))
219                 .append(", searchDomains=").append(toString(searchDomains))
220                 .append(", allowedApps=").append(toString(allowedApplications))
221                 .append(", disallowedApps=").append(toString(disallowedApplications))
222                 .append(", configureIntent=").append(configureIntent)
223                 .append(", startTime=").append(startTime)
224                 .append(", legacy=").append(legacy)
225                 .append(", blocking=").append(blocking)
226                 .append(", allowBypass=").append(allowBypass)
227                 .append(", allowIPv4=").append(allowIPv4)
228                 .append(", allowIPv6=").append(allowIPv6)
229                 .append(", underlyingNetworks=").append(Arrays.toString(underlyingNetworks))
230                 .append(", proxyInfo=").append(proxyInfo.toString())
231                 .append("}")
232                 .toString();
233     }
234 
toString(List<T> ls)235     static <T> String toString(List<T> ls) {
236         if (ls == null) {
237             return "null";
238         }
239         return Arrays.toString(ls.toArray());
240     }
241 }
242