123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333 |
- // Copyright (c) 2012 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "net/android/network_library.h"
- #include <dlfcn.h>
- #include <string>
- #include <vector>
- #include "base/android/build_info.h"
- #include "base/android/jni_android.h"
- #include "base/android/jni_array.h"
- #include "base/android/jni_string.h"
- #include "base/android/scoped_java_ref.h"
- #include "base/check_op.h"
- #include "base/native_library.h"
- #include "base/strings/string_split.h"
- #include "base/strings/utf_string_conversions.h"
- #include "net/base/net_errors.h"
- #include "net/dns/public/dns_protocol.h"
- #include "net/net_jni_headers/AndroidNetworkLibrary_jni.h"
- #include "net/net_jni_headers/DnsStatus_jni.h"
- using base::android::AttachCurrentThread;
- using base::android::ConvertJavaStringToUTF8;
- using base::android::ConvertUTF8ToJavaString;
- using base::android::ScopedJavaLocalRef;
- using base::android::ToJavaArrayOfByteArray;
- using base::android::ToJavaByteArray;
- namespace net::android {
- void 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) {
- JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jobjectArray> chain_byte_array =
- ToJavaArrayOfByteArray(env, cert_chain);
- DCHECK(!chain_byte_array.is_null());
- ScopedJavaLocalRef<jstring> auth_string =
- ConvertUTF8ToJavaString(env, auth_type);
- DCHECK(!auth_string.is_null());
- ScopedJavaLocalRef<jstring> host_string =
- ConvertUTF8ToJavaString(env, host);
- DCHECK(!host_string.is_null());
- ScopedJavaLocalRef<jobject> result =
- Java_AndroidNetworkLibrary_verifyServerCertificates(
- env, chain_byte_array, auth_string, host_string);
- ExtractCertVerifyResult(result, status, is_issued_by_known_root,
- verified_chain);
- }
- void AddTestRootCertificate(const uint8_t* cert, size_t len) {
- JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jbyteArray> cert_array = ToJavaByteArray(env, cert, len);
- DCHECK(!cert_array.is_null());
- Java_AndroidNetworkLibrary_addTestRootCertificate(env, cert_array);
- }
- void ClearTestRootCertificates() {
- JNIEnv* env = AttachCurrentThread();
- Java_AndroidNetworkLibrary_clearTestRootCertificates(env);
- }
- bool IsCleartextPermitted(const std::string& host) {
- JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jstring> host_string = ConvertUTF8ToJavaString(env, host);
- return Java_AndroidNetworkLibrary_isCleartextPermitted(env, host_string);
- }
- bool HaveOnlyLoopbackAddresses() {
- JNIEnv* env = AttachCurrentThread();
- return Java_AndroidNetworkLibrary_haveOnlyLoopbackAddresses(env);
- }
- bool GetMimeTypeFromExtension(const std::string& extension,
- std::string* result) {
- JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jstring> extension_string =
- ConvertUTF8ToJavaString(env, extension);
- ScopedJavaLocalRef<jstring> ret =
- Java_AndroidNetworkLibrary_getMimeTypeFromExtension(env,
- extension_string);
- if (!ret.obj())
- return false;
- *result = ConvertJavaStringToUTF8(ret);
- return true;
- }
- std::string GetTelephonyNetworkOperator() {
- return base::android::ConvertJavaStringToUTF8(
- Java_AndroidNetworkLibrary_getNetworkOperator(
- base::android::AttachCurrentThread()));
- }
- bool GetIsRoaming() {
- return Java_AndroidNetworkLibrary_getIsRoaming(
- base::android::AttachCurrentThread());
- }
- bool GetIsCaptivePortal() {
- return Java_AndroidNetworkLibrary_getIsCaptivePortal(
- base::android::AttachCurrentThread());
- }
- std::string GetWifiSSID() {
- return base::android::ConvertJavaStringToUTF8(
- Java_AndroidNetworkLibrary_getWifiSSID(
- base::android::AttachCurrentThread()));
- }
- void SetWifiEnabledForTesting(bool enabled) {
- Java_AndroidNetworkLibrary_setWifiEnabled(
- base::android::AttachCurrentThread(), enabled);
- }
- absl::optional<int32_t> GetWifiSignalLevel() {
- const int count_buckets = 5;
- int signal_strength = Java_AndroidNetworkLibrary_getWifiSignalLevel(
- base::android::AttachCurrentThread(), count_buckets);
- if (signal_strength < 0)
- return absl::nullopt;
- DCHECK_LE(0, signal_strength);
- DCHECK_GE(count_buckets - 1, signal_strength);
- return signal_strength;
- }
- namespace {
- bool 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) {
- // Parse the DNS servers.
- std::vector<std::vector<uint8_t>> dns_servers_data;
- base::android::JavaArrayOfByteArrayToBytesVector(
- env, Java_DnsStatus_getDnsServers(env, dns_status), &dns_servers_data);
- for (const std::vector<uint8_t>& dns_address_data : dns_servers_data) {
- IPAddress dns_address(dns_address_data.data(), dns_address_data.size());
- IPEndPoint dns_server(dns_address, dns_protocol::kDefaultPort);
- dns_servers->push_back(dns_server);
- }
- *dns_over_tls_active = Java_DnsStatus_getPrivateDnsActive(env, dns_status);
- *dns_over_tls_hostname = base::android::ConvertJavaStringToUTF8(
- Java_DnsStatus_getPrivateDnsServerName(env, dns_status));
- std::string search_suffixes_str = base::android::ConvertJavaStringToUTF8(
- Java_DnsStatus_getSearchDomains(env, dns_status));
- *search_suffixes =
- base::SplitString(search_suffixes_str, ",", base::TRIM_WHITESPACE,
- base::SPLIT_WANT_NONEMPTY);
- return !dns_servers->empty();
- }
- } // namespace
- bool GetCurrentDnsServers(std::vector<IPEndPoint>* dns_servers,
- bool* dns_over_tls_active,
- std::string* dns_over_tls_hostname,
- std::vector<std::string>* search_suffixes) {
- DCHECK_GE(base::android::BuildInfo::GetInstance()->sdk_int(),
- base::android::SDK_VERSION_MARSHMALLOW);
- JNIEnv* env = AttachCurrentThread();
- // Get the DNS status for the current default network.
- ScopedJavaLocalRef<jobject> result =
- Java_AndroidNetworkLibrary_getCurrentDnsStatus(env);
- if (result.is_null())
- return false;
- return GetDnsServersInternal(env, result, dns_servers, dns_over_tls_active,
- dns_over_tls_hostname, search_suffixes);
- }
- bool 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) {
- DCHECK_GE(base::android::BuildInfo::GetInstance()->sdk_int(),
- base::android::SDK_VERSION_P);
- JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jobject> result =
- Java_AndroidNetworkLibrary_getDnsStatusForNetwork(env, network);
- if (result.is_null())
- return false;
- return GetDnsServersInternal(env, result, dns_servers, dns_over_tls_active,
- dns_over_tls_hostname, search_suffixes);
- }
- bool ReportBadDefaultNetwork() {
- return Java_AndroidNetworkLibrary_reportBadDefaultNetwork(
- AttachCurrentThread());
- }
- void TagSocket(SocketDescriptor socket, uid_t uid, int32_t tag) {
- Java_AndroidNetworkLibrary_tagSocket(AttachCurrentThread(), socket, uid, tag);
- }
- namespace {
- using LollipopSetNetworkForSocket = int (*)(unsigned net_id, int socket_fd);
- using MarshmallowSetNetworkForSocket = int (*)(int64_t net_id, int socket_fd);
- MarshmallowSetNetworkForSocket GetMarshmallowSetNetworkForSocket() {
- // On Android M and newer releases use supported NDK API.
- base::FilePath file(base::GetNativeLibraryName("android"));
- // See declaration of android_setsocknetwork() here:
- // http://androidxref.com/6.0.0_r1/xref/development/ndk/platforms/android-M/include/android/multinetwork.h#65
- // Function cannot be called directly as it will cause app to fail to load on
- // pre-marshmallow devices.
- void* dl = dlopen(file.value().c_str(), RTLD_NOW);
- return reinterpret_cast<MarshmallowSetNetworkForSocket>(
- dlsym(dl, "android_setsocknetwork"));
- }
- LollipopSetNetworkForSocket GetLollipopSetNetworkForSocket() {
- // On Android L use setNetworkForSocket from libnetd_client.so. Android's netd
- // client library should always be loaded in our address space as it shims
- // socket().
- base::FilePath file(base::GetNativeLibraryName("netd_client"));
- // Use RTLD_NOW to match Android's prior loading of the library:
- // http://androidxref.com/6.0.0_r5/xref/bionic/libc/bionic/NetdClient.cpp#37
- // Use RTLD_NOLOAD to assert that the library is already loaded and avoid
- // doing any disk IO.
- void* dl = dlopen(file.value().c_str(), RTLD_NOW | RTLD_NOLOAD);
- return reinterpret_cast<LollipopSetNetworkForSocket>(
- dlsym(dl, "setNetworkForSocket"));
- }
- } // namespace
- int BindToNetwork(SocketDescriptor socket, handles::NetworkHandle network) {
- DCHECK_NE(socket, kInvalidSocket);
- if (network == handles::kInvalidNetworkHandle)
- return ERR_INVALID_ARGUMENT;
- // Android prior to Lollipop didn't have support for binding sockets to
- // networks.
- if (base::android::BuildInfo::GetInstance()->sdk_int() <
- base::android::SDK_VERSION_LOLLIPOP)
- return ERR_NOT_IMPLEMENTED;
- int rv;
- if (base::android::BuildInfo::GetInstance()->sdk_int() >=
- base::android::SDK_VERSION_MARSHMALLOW) {
- static MarshmallowSetNetworkForSocket marshmallow_set_network_for_socket =
- GetMarshmallowSetNetworkForSocket();
- if (!marshmallow_set_network_for_socket)
- return ERR_NOT_IMPLEMENTED;
- rv = marshmallow_set_network_for_socket(network, socket);
- if (rv)
- rv = errno;
- } else {
- static LollipopSetNetworkForSocket lollipop_set_network_for_socket =
- GetLollipopSetNetworkForSocket();
- if (!lollipop_set_network_for_socket)
- return ERR_NOT_IMPLEMENTED;
- rv = -lollipop_set_network_for_socket(network, socket);
- }
- // If |network| has since disconnected, |rv| will be ENONET. Surface this as
- // ERR_NETWORK_CHANGED, rather than MapSystemError(ENONET) which gives back
- // the less descriptive ERR_FAILED.
- if (rv == ENONET)
- return ERR_NETWORK_CHANGED;
- return MapSystemError(rv);
- }
- namespace {
- using MarshmallowGetAddrInfoForNetwork = int (*)(int64_t network,
- const char* node,
- const char* service,
- const struct addrinfo* hints,
- struct addrinfo** res);
- MarshmallowGetAddrInfoForNetwork GetMarshmallowGetAddrInfoForNetwork() {
- // On Android M and newer releases use supported NDK API.
- base::FilePath file(base::GetNativeLibraryName("android"));
- // See declaration of android_getaddrinfofornetwork() here:
- // https://developer.android.com/ndk/reference/group/networking#android_getaddrinfofornetwork
- // Function cannot be called directly as it will cause app to fail to load on
- // pre-marshmallow devices.
- void* dl = dlopen(file.value().c_str(), RTLD_NOW);
- return reinterpret_cast<MarshmallowGetAddrInfoForNetwork>(
- dlsym(dl, "android_getaddrinfofornetwork"));
- }
- } // namespace
- NET_EXPORT_PRIVATE int GetAddrInfoForNetwork(handles::NetworkHandle network,
- const char* node,
- const char* service,
- const struct addrinfo* hints,
- struct addrinfo** res) {
- if (network == handles::kInvalidNetworkHandle) {
- errno = EINVAL;
- return EAI_SYSTEM;
- }
- if (base::android::BuildInfo::GetInstance()->sdk_int() <
- base::android::SDK_VERSION_MARSHMALLOW) {
- errno = ENOSYS;
- return EAI_SYSTEM;
- }
- static MarshmallowGetAddrInfoForNetwork get_addrinfo_for_network =
- GetMarshmallowGetAddrInfoForNetwork();
- if (!get_addrinfo_for_network) {
- errno = ENOSYS;
- return EAI_SYSTEM;
- }
- return get_addrinfo_for_network(network, node, service, hints, res);
- }
- } // namespace net::android
|