xref: /aosp_15_r20/external/cronet/net/android/network_library.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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