• 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 <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 "base/threading/scoped_blocking_call.h"
22 #include "net/base/net_errors.h"
23 #include "net/dns/public/dns_protocol.h"
24 #include "net/net_jni_headers/AndroidNetworkLibrary_jni.h"
25 #include "net/net_jni_headers/DnsStatus_jni.h"
26 
27 using base::android::AttachCurrentThread;
28 using base::android::ConvertJavaStringToUTF8;
29 using base::android::ConvertUTF8ToJavaString;
30 using base::android::JavaArrayOfByteArrayToStringVector;
31 using base::android::ScopedJavaLocalRef;
32 using base::android::ToJavaArrayOfByteArray;
33 using base::android::ToJavaByteArray;
34 
35 namespace net::android {
36 
GetUserAddedRoots()37 std::vector<std::string> GetUserAddedRoots() {
38   std::vector<std::string> roots;
39   JNIEnv* env = AttachCurrentThread();
40 
41   ScopedJavaLocalRef<jobjectArray> roots_byte_array =
42       Java_AndroidNetworkLibrary_getUserAddedRoots(env);
43   JavaArrayOfByteArrayToStringVector(env, roots_byte_array, &roots);
44   return roots;
45 }
46 
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)47 void VerifyX509CertChain(const std::vector<std::string>& cert_chain,
48                          base::StringPiece auth_type,
49                          base::StringPiece host,
50                          CertVerifyStatusAndroid* status,
51                          bool* is_issued_by_known_root,
52                          std::vector<std::string>* verified_chain) {
53   JNIEnv* env = AttachCurrentThread();
54 
55   ScopedJavaLocalRef<jobjectArray> chain_byte_array =
56       ToJavaArrayOfByteArray(env, cert_chain);
57   DCHECK(!chain_byte_array.is_null());
58 
59   ScopedJavaLocalRef<jstring> auth_string =
60       ConvertUTF8ToJavaString(env, auth_type);
61   DCHECK(!auth_string.is_null());
62 
63   ScopedJavaLocalRef<jstring> host_string =
64       ConvertUTF8ToJavaString(env, host);
65   DCHECK(!host_string.is_null());
66 
67   ScopedJavaLocalRef<jobject> result =
68       Java_AndroidNetworkLibrary_verifyServerCertificates(
69           env, chain_byte_array, auth_string, host_string);
70 
71   ExtractCertVerifyResult(result, status, is_issued_by_known_root,
72                           verified_chain);
73 }
74 
AddTestRootCertificate(const uint8_t * cert,size_t len)75 void AddTestRootCertificate(const uint8_t* cert, size_t len) {
76   JNIEnv* env = AttachCurrentThread();
77   ScopedJavaLocalRef<jbyteArray> cert_array = ToJavaByteArray(env, cert, len);
78   DCHECK(!cert_array.is_null());
79   Java_AndroidNetworkLibrary_addTestRootCertificate(env, cert_array);
80 }
81 
ClearTestRootCertificates()82 void ClearTestRootCertificates() {
83   JNIEnv* env = AttachCurrentThread();
84   Java_AndroidNetworkLibrary_clearTestRootCertificates(env);
85 }
86 
IsCleartextPermitted(base::StringPiece host)87 bool IsCleartextPermitted(base::StringPiece host) {
88   JNIEnv* env = AttachCurrentThread();
89   ScopedJavaLocalRef<jstring> host_string = ConvertUTF8ToJavaString(env, host);
90   return Java_AndroidNetworkLibrary_isCleartextPermitted(env, host_string);
91 }
92 
HaveOnlyLoopbackAddresses()93 bool HaveOnlyLoopbackAddresses() {
94   base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
95                                                 base::BlockingType::MAY_BLOCK);
96   JNIEnv* env = AttachCurrentThread();
97   return Java_AndroidNetworkLibrary_haveOnlyLoopbackAddresses(env);
98 }
99 
GetMimeTypeFromExtension(base::StringPiece extension,std::string * result)100 bool GetMimeTypeFromExtension(base::StringPiece extension,
101                               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 absl::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 absl::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.data(), dns_address_data.size());
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