• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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