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