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