1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/android/network_library.h"
6
7 #include <dlfcn.h>
8
9 #include <string>
10 #include <vector>
11
12 #include "base/android/build_info.h"
13 #include "base/android/jni_android.h"
14 #include "base/android/jni_array.h"
15 #include "base/android/jni_string.h"
16 #include "base/android/scoped_java_ref.h"
17 #include "base/check_op.h"
18 #include "base/native_library.h"
19 #include "base/strings/string_split.h"
20 #include "base/strings/utf_string_conversions.h"
21 #include "net/base/net_errors.h"
22 #include "net/dns/public/dns_protocol.h"
23 #include "net/net_jni_headers/AndroidNetworkLibrary_jni.h"
24 #include "net/net_jni_headers/DnsStatus_jni.h"
25
26 using base::android::AttachCurrentThread;
27 using base::android::ConvertJavaStringToUTF8;
28 using base::android::ConvertUTF8ToJavaString;
29 using base::android::JavaArrayOfByteArrayToStringVector;
30 using base::android::ScopedJavaLocalRef;
31 using base::android::ToJavaArrayOfByteArray;
32 using base::android::ToJavaByteArray;
33
34 namespace net::android {
35
GetUserAddedRoots()36 std::vector<std::string> GetUserAddedRoots() {
37 std::vector<std::string> roots;
38 JNIEnv* env = AttachCurrentThread();
39
40 ScopedJavaLocalRef<jobjectArray> roots_byte_array =
41 Java_AndroidNetworkLibrary_getUserAddedRoots(env);
42 JavaArrayOfByteArrayToStringVector(env, roots_byte_array, &roots);
43 return roots;
44 }
45
VerifyX509CertChain(const std::vector<std::string> & cert_chain,base::StringPiece auth_type,base::StringPiece host,CertVerifyStatusAndroid * status,bool * is_issued_by_known_root,std::vector<std::string> * verified_chain)46 void VerifyX509CertChain(const std::vector<std::string>& cert_chain,
47 base::StringPiece auth_type,
48 base::StringPiece host,
49 CertVerifyStatusAndroid* status,
50 bool* is_issued_by_known_root,
51 std::vector<std::string>* verified_chain) {
52 JNIEnv* env = AttachCurrentThread();
53
54 ScopedJavaLocalRef<jobjectArray> chain_byte_array =
55 ToJavaArrayOfByteArray(env, cert_chain);
56 DCHECK(!chain_byte_array.is_null());
57
58 ScopedJavaLocalRef<jstring> auth_string =
59 ConvertUTF8ToJavaString(env, auth_type);
60 DCHECK(!auth_string.is_null());
61
62 ScopedJavaLocalRef<jstring> host_string =
63 ConvertUTF8ToJavaString(env, host);
64 DCHECK(!host_string.is_null());
65
66 ScopedJavaLocalRef<jobject> result =
67 Java_AndroidNetworkLibrary_verifyServerCertificates(
68 env, chain_byte_array, auth_string, host_string);
69
70 ExtractCertVerifyResult(result, status, is_issued_by_known_root,
71 verified_chain);
72 }
73
AddTestRootCertificate(const uint8_t * cert,size_t len)74 void AddTestRootCertificate(const uint8_t* cert, size_t len) {
75 JNIEnv* env = AttachCurrentThread();
76 ScopedJavaLocalRef<jbyteArray> cert_array = ToJavaByteArray(env, cert, len);
77 DCHECK(!cert_array.is_null());
78 Java_AndroidNetworkLibrary_addTestRootCertificate(env, cert_array);
79 }
80
ClearTestRootCertificates()81 void ClearTestRootCertificates() {
82 JNIEnv* env = AttachCurrentThread();
83 Java_AndroidNetworkLibrary_clearTestRootCertificates(env);
84 }
85
IsCleartextPermitted(const std::string & host)86 bool IsCleartextPermitted(const std::string& host) {
87 JNIEnv* env = AttachCurrentThread();
88 ScopedJavaLocalRef<jstring> host_string = ConvertUTF8ToJavaString(env, host);
89 return Java_AndroidNetworkLibrary_isCleartextPermitted(env, host_string);
90 }
91
HaveOnlyLoopbackAddresses()92 bool HaveOnlyLoopbackAddresses() {
93 JNIEnv* env = AttachCurrentThread();
94 return Java_AndroidNetworkLibrary_haveOnlyLoopbackAddresses(env);
95 }
96
GetMimeTypeFromExtension(const std::string & extension,std::string * result)97 bool GetMimeTypeFromExtension(const std::string& extension,
98 std::string* result) {
99 JNIEnv* env = AttachCurrentThread();
100
101 ScopedJavaLocalRef<jstring> extension_string =
102 ConvertUTF8ToJavaString(env, extension);
103 ScopedJavaLocalRef<jstring> ret =
104 Java_AndroidNetworkLibrary_getMimeTypeFromExtension(env,
105 extension_string);
106
107 if (!ret.obj())
108 return false;
109 *result = ConvertJavaStringToUTF8(ret);
110 return true;
111 }
112
GetTelephonyNetworkOperator()113 std::string GetTelephonyNetworkOperator() {
114 return base::android::ConvertJavaStringToUTF8(
115 Java_AndroidNetworkLibrary_getNetworkOperator(
116 base::android::AttachCurrentThread()));
117 }
118
GetIsRoaming()119 bool GetIsRoaming() {
120 return Java_AndroidNetworkLibrary_getIsRoaming(
121 base::android::AttachCurrentThread());
122 }
123
GetIsCaptivePortal()124 bool GetIsCaptivePortal() {
125 return Java_AndroidNetworkLibrary_getIsCaptivePortal(
126 base::android::AttachCurrentThread());
127 }
128
GetWifiSSID()129 std::string GetWifiSSID() {
130 return base::android::ConvertJavaStringToUTF8(
131 Java_AndroidNetworkLibrary_getWifiSSID(
132 base::android::AttachCurrentThread()));
133 }
134
SetWifiEnabledForTesting(bool enabled)135 void SetWifiEnabledForTesting(bool enabled) {
136 Java_AndroidNetworkLibrary_setWifiEnabled(
137 base::android::AttachCurrentThread(), enabled);
138 }
139
GetWifiSignalLevel()140 absl::optional<int32_t> GetWifiSignalLevel() {
141 const int count_buckets = 5;
142 int signal_strength = Java_AndroidNetworkLibrary_getWifiSignalLevel(
143 base::android::AttachCurrentThread(), count_buckets);
144 if (signal_strength < 0)
145 return absl::nullopt;
146 DCHECK_LE(0, signal_strength);
147 DCHECK_GE(count_buckets - 1, signal_strength);
148
149 return signal_strength;
150 }
151
152 namespace {
153
GetDnsServersInternal(JNIEnv * env,const base::android::JavaRef<jobject> & dns_status,std::vector<IPEndPoint> * dns_servers,bool * dns_over_tls_active,std::string * dns_over_tls_hostname,std::vector<std::string> * search_suffixes)154 bool GetDnsServersInternal(JNIEnv* env,
155 const base::android::JavaRef<jobject>& dns_status,
156 std::vector<IPEndPoint>* dns_servers,
157 bool* dns_over_tls_active,
158 std::string* dns_over_tls_hostname,
159 std::vector<std::string>* search_suffixes) {
160 // Parse the DNS servers.
161 std::vector<std::vector<uint8_t>> dns_servers_data;
162 base::android::JavaArrayOfByteArrayToBytesVector(
163 env, Java_DnsStatus_getDnsServers(env, dns_status), &dns_servers_data);
164 for (const std::vector<uint8_t>& dns_address_data : dns_servers_data) {
165 IPAddress dns_address(dns_address_data.data(), dns_address_data.size());
166 IPEndPoint dns_server(dns_address, dns_protocol::kDefaultPort);
167 dns_servers->push_back(dns_server);
168 }
169
170 *dns_over_tls_active = Java_DnsStatus_getPrivateDnsActive(env, dns_status);
171 *dns_over_tls_hostname = base::android::ConvertJavaStringToUTF8(
172 Java_DnsStatus_getPrivateDnsServerName(env, dns_status));
173
174 std::string search_suffixes_str = base::android::ConvertJavaStringToUTF8(
175 Java_DnsStatus_getSearchDomains(env, dns_status));
176 *search_suffixes =
177 base::SplitString(search_suffixes_str, ",", base::TRIM_WHITESPACE,
178 base::SPLIT_WANT_NONEMPTY);
179
180 return !dns_servers->empty();
181 }
182
183 } // namespace
184
GetCurrentDnsServers(std::vector<IPEndPoint> * dns_servers,bool * dns_over_tls_active,std::string * dns_over_tls_hostname,std::vector<std::string> * search_suffixes)185 bool GetCurrentDnsServers(std::vector<IPEndPoint>* dns_servers,
186 bool* dns_over_tls_active,
187 std::string* dns_over_tls_hostname,
188 std::vector<std::string>* search_suffixes) {
189 DCHECK_GE(base::android::BuildInfo::GetInstance()->sdk_int(),
190 base::android::SDK_VERSION_MARSHMALLOW);
191
192 JNIEnv* env = AttachCurrentThread();
193 // Get the DNS status for the current default network.
194 ScopedJavaLocalRef<jobject> result =
195 Java_AndroidNetworkLibrary_getCurrentDnsStatus(env);
196 if (result.is_null())
197 return false;
198 return GetDnsServersInternal(env, result, dns_servers, dns_over_tls_active,
199 dns_over_tls_hostname, search_suffixes);
200 }
201
GetDnsServersForNetwork(std::vector<IPEndPoint> * dns_servers,bool * dns_over_tls_active,std::string * dns_over_tls_hostname,std::vector<std::string> * search_suffixes,handles::NetworkHandle network)202 bool GetDnsServersForNetwork(std::vector<IPEndPoint>* dns_servers,
203 bool* dns_over_tls_active,
204 std::string* dns_over_tls_hostname,
205 std::vector<std::string>* search_suffixes,
206 handles::NetworkHandle network) {
207 DCHECK_GE(base::android::BuildInfo::GetInstance()->sdk_int(),
208 base::android::SDK_VERSION_P);
209
210 JNIEnv* env = AttachCurrentThread();
211 ScopedJavaLocalRef<jobject> result =
212 Java_AndroidNetworkLibrary_getDnsStatusForNetwork(env, network);
213 if (result.is_null())
214 return false;
215 return GetDnsServersInternal(env, result, dns_servers, dns_over_tls_active,
216 dns_over_tls_hostname, search_suffixes);
217 }
218
ReportBadDefaultNetwork()219 bool ReportBadDefaultNetwork() {
220 return Java_AndroidNetworkLibrary_reportBadDefaultNetwork(
221 AttachCurrentThread());
222 }
223
TagSocket(SocketDescriptor socket,uid_t uid,int32_t tag)224 void TagSocket(SocketDescriptor socket, uid_t uid, int32_t tag) {
225 Java_AndroidNetworkLibrary_tagSocket(AttachCurrentThread(), socket, uid, tag);
226 }
227
228 namespace {
229
230 using LollipopSetNetworkForSocket = int (*)(unsigned net_id, int socket_fd);
231 using MarshmallowSetNetworkForSocket = int (*)(int64_t net_id, int socket_fd);
232
GetMarshmallowSetNetworkForSocket()233 MarshmallowSetNetworkForSocket GetMarshmallowSetNetworkForSocket() {
234 // On Android M and newer releases use supported NDK API.
235 base::FilePath file(base::GetNativeLibraryName("android"));
236 // See declaration of android_setsocknetwork() here:
237 // http://androidxref.com/6.0.0_r1/xref/development/ndk/platforms/android-M/include/android/multinetwork.h#65
238 // Function cannot be called directly as it will cause app to fail to load on
239 // pre-marshmallow devices.
240 void* dl = dlopen(file.value().c_str(), RTLD_NOW);
241 return reinterpret_cast<MarshmallowSetNetworkForSocket>(
242 dlsym(dl, "android_setsocknetwork"));
243 }
244
GetLollipopSetNetworkForSocket()245 LollipopSetNetworkForSocket GetLollipopSetNetworkForSocket() {
246 // On Android L use setNetworkForSocket from libnetd_client.so. Android's netd
247 // client library should always be loaded in our address space as it shims
248 // socket().
249 base::FilePath file(base::GetNativeLibraryName("netd_client"));
250 // Use RTLD_NOW to match Android's prior loading of the library:
251 // http://androidxref.com/6.0.0_r5/xref/bionic/libc/bionic/NetdClient.cpp#37
252 // Use RTLD_NOLOAD to assert that the library is already loaded and avoid
253 // doing any disk IO.
254 void* dl = dlopen(file.value().c_str(), RTLD_NOW | RTLD_NOLOAD);
255 return reinterpret_cast<LollipopSetNetworkForSocket>(
256 dlsym(dl, "setNetworkForSocket"));
257 }
258
259 } // namespace
260
BindToNetwork(SocketDescriptor socket,handles::NetworkHandle network)261 int BindToNetwork(SocketDescriptor socket, handles::NetworkHandle network) {
262 DCHECK_NE(socket, kInvalidSocket);
263 if (network == handles::kInvalidNetworkHandle)
264 return ERR_INVALID_ARGUMENT;
265
266 // Android prior to Lollipop didn't have support for binding sockets to
267 // networks.
268 if (base::android::BuildInfo::GetInstance()->sdk_int() <
269 base::android::SDK_VERSION_LOLLIPOP)
270 return ERR_NOT_IMPLEMENTED;
271
272 int rv;
273 if (base::android::BuildInfo::GetInstance()->sdk_int() >=
274 base::android::SDK_VERSION_MARSHMALLOW) {
275 static MarshmallowSetNetworkForSocket marshmallow_set_network_for_socket =
276 GetMarshmallowSetNetworkForSocket();
277 if (!marshmallow_set_network_for_socket)
278 return ERR_NOT_IMPLEMENTED;
279 rv = marshmallow_set_network_for_socket(network, socket);
280 if (rv)
281 rv = errno;
282 } else {
283 static LollipopSetNetworkForSocket lollipop_set_network_for_socket =
284 GetLollipopSetNetworkForSocket();
285 if (!lollipop_set_network_for_socket)
286 return ERR_NOT_IMPLEMENTED;
287 rv = -lollipop_set_network_for_socket(network, socket);
288 }
289 // If |network| has since disconnected, |rv| will be ENONET. Surface this as
290 // ERR_NETWORK_CHANGED, rather than MapSystemError(ENONET) which gives back
291 // the less descriptive ERR_FAILED.
292 if (rv == ENONET)
293 return ERR_NETWORK_CHANGED;
294 return MapSystemError(rv);
295 }
296
297 namespace {
298
299 using MarshmallowGetAddrInfoForNetwork = int (*)(int64_t network,
300 const char* node,
301 const char* service,
302 const struct addrinfo* hints,
303 struct addrinfo** res);
304
GetMarshmallowGetAddrInfoForNetwork()305 MarshmallowGetAddrInfoForNetwork GetMarshmallowGetAddrInfoForNetwork() {
306 // On Android M and newer releases use supported NDK API.
307 base::FilePath file(base::GetNativeLibraryName("android"));
308 // See declaration of android_getaddrinfofornetwork() here:
309 // https://developer.android.com/ndk/reference/group/networking#android_getaddrinfofornetwork
310 // Function cannot be called directly as it will cause app to fail to load on
311 // pre-marshmallow devices.
312 void* dl = dlopen(file.value().c_str(), RTLD_NOW);
313 return reinterpret_cast<MarshmallowGetAddrInfoForNetwork>(
314 dlsym(dl, "android_getaddrinfofornetwork"));
315 }
316
317 } // namespace
318
GetAddrInfoForNetwork(handles::NetworkHandle network,const char * node,const char * service,const struct addrinfo * hints,struct addrinfo ** res)319 NET_EXPORT_PRIVATE int GetAddrInfoForNetwork(handles::NetworkHandle network,
320 const char* node,
321 const char* service,
322 const struct addrinfo* hints,
323 struct addrinfo** res) {
324 if (network == handles::kInvalidNetworkHandle) {
325 errno = EINVAL;
326 return EAI_SYSTEM;
327 }
328 if (base::android::BuildInfo::GetInstance()->sdk_int() <
329 base::android::SDK_VERSION_MARSHMALLOW) {
330 errno = ENOSYS;
331 return EAI_SYSTEM;
332 }
333
334 static MarshmallowGetAddrInfoForNetwork get_addrinfo_for_network =
335 GetMarshmallowGetAddrInfoForNetwork();
336 if (!get_addrinfo_for_network) {
337 errno = ENOSYS;
338 return EAI_SYSTEM;
339 }
340
341 return get_addrinfo_for_network(network, node, service, hints, res);
342 }
343
344 } // namespace net::android
345