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