Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 566724af authored by android-build-team Robot's avatar android-build-team Robot
Browse files

Snap for 7447420 from f87a3001 to...

Snap for 7447420 from f87a3001 to mainline-captiveportallogin-release

Change-Id: Ibd36d6ad89dccfdaa394d7ce5cd9987309e95833
parents e97e69a1 f87a3001
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -214,8 +214,8 @@ DnsTlsTransport::Response DnsTlsDispatcher::query(const DnsTlsServer& server, un
            // happens, the xport will be marked as unusable and DoT queries won't be sent to
            // it anymore. Eventually, after IDLE_TIMEOUT, the xport will be destroyed, and
            // a new xport will be created.
            const auto result =
                    PrivateDnsConfiguration::getInstance().requestValidation(netId, server, mark);
            const auto result = PrivateDnsConfiguration::getInstance().requestValidation(
                    netId, PrivateDnsConfiguration::ServerIdentity{server}, mark);
            LOG(WARNING) << "Requested validation for " << server.toIpString() << " with mark 0x"
                         << std::hex << mark << ", "
                         << (result.ok() ? "succeeded" : "failed: " + result.error().message());
+15 −6
Original line number Diff line number Diff line
@@ -24,14 +24,14 @@

#include <params.h>

#include "PrivateDnsCommon.h"
#include "IPrivateDnsServer.h"

namespace android {
namespace net {

// DnsTlsServer represents a recursive resolver that supports, or may support, a
// secure protocol.
struct DnsTlsServer {
struct DnsTlsServer : public IPrivateDnsServer {
    // Default constructor.
    DnsTlsServer() {}

@@ -63,8 +63,17 @@ struct DnsTlsServer {
    bool wasExplicitlyConfigured() const;
    std::string toIpString() const;

    Validation validationState() const { return mValidation; }
    void setValidationState(Validation val) { mValidation = val; }
    PrivateDnsTransport transport() const override { return PrivateDnsTransport::kDot; }
    std::string provider() const override { return name; }
    netdutils::IPSockAddr addr() const override { return netdutils::IPSockAddr::toIPSockAddr(ss); }
    uint32_t validationMark() const override { return mark; }

    Validation validationState() const override { return mValidation; }
    void setValidationState(Validation val) override { mValidation = val; }
    bool probe() override {
        // TODO: implement it.
        return false;
    }

    // The socket mark used for validation.
    // Note that the mark of a connection to which the DnsResolver sends app's DNS requests can
@@ -74,8 +83,8 @@ struct DnsTlsServer {

    // Return whether or not the server can be used for a network. It depends on
    // the resolver configuration.
    bool active() const { return mActive; }
    void setActive(bool val) { mActive = val; }
    bool active() const override { return mActive; }
    void setActive(bool val) override { mActive = val; }

  private:
    // State, unrelated to the comparison of DnsTlsServer objects.

IPrivateDnsServer.h

0 → 100644
+60 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

#include <string>

#include <netdutils/InternetAddresses.h>

#include "PrivateDnsCommon.h"

namespace android::net {

class IPrivateDnsServer {
  public:
    virtual ~IPrivateDnsServer(){};

    virtual PrivateDnsTransport transport() const = 0;
    bool isDot() const { return transport() == PrivateDnsTransport::kDot; }
    bool isDoh() const { return transport() == PrivateDnsTransport::kDoh; }

    // Returns the provider name of the server.
    virtual std::string provider() const = 0;

    // Returns the IP address of the server.
    virtual netdutils::IPSockAddr addr() const = 0;

    // Returns the socket mark used for probe.
    virtual uint32_t validationMark() const = 0;

    // Sets the validation state.
    virtual void setValidationState(Validation val) = 0;

    // Returns the validation state.
    virtual Validation validationState() const = 0;

    // Checks the server supports private DNS.
    virtual bool probe() = 0;

    // Sets if the server should be active.
    virtual void setActive(bool val) = 0;

    // Returns if the server is active.
    virtual bool active() const = 0;
};

}  // namespace android::net
+5 −0
Original line number Diff line number Diff line
@@ -18,6 +18,11 @@

namespace android::net {

enum class PrivateDnsTransport : uint8_t {
    kDot,  // DNS over TLS.
    kDoh,  // DNS over HTTPS.
};

// Validation status of a private DNS server on a specific netId.
enum class Validation : uint8_t {
    in_process,
+79 −63
Original line number Diff line number Diff line
@@ -70,11 +70,11 @@ int PrivateDnsConfiguration::set(int32_t netId, uint32_t mark,
        if (!parseServer(s.c_str(), &parsed)) {
            return -EINVAL;
        }
        DnsTlsServer server(parsed);
        server.name = name;
        server.certificate = caCert;
        server.mark = mark;
        tmp[ServerIdentity(server)] = server;
        auto server = std::make_unique<DnsTlsServer>(parsed);
        server->name = name;
        server->certificate = caCert;
        server->mark = mark;
        tmp[ServerIdentity(*server)] = std::move(server);
    }

    std::lock_guard guard(mPrivateDnsLock);
@@ -93,24 +93,24 @@ int PrivateDnsConfiguration::set(int32_t netId, uint32_t mark,
    auto& tracker = mPrivateDnsTransports[netId];

    // Add the servers if not contained in tracker.
    for (const auto& [identity, server] : tmp) {
    for (auto& [identity, server] : tmp) {
        if (tracker.find(identity) == tracker.end()) {
            tracker[identity] = server;
            tracker[identity] = std::move(server);
        }
    }

    for (auto& [identity, server] : tracker) {
        const bool active = tmp.find(identity) != tmp.end();
        server.setActive(active);
        server->setActive(active);

        // For simplicity, deem the validation result of inactive servers as unreliable.
        if (!server.active() && server.validationState() == Validation::success) {
        if (!server->active() && server->validationState() == Validation::success) {
            updateServerState(identity, Validation::success_but_expired, netId);
        }

        if (needsValidation(server)) {
        if (needsValidation(*server)) {
            updateServerState(identity, Validation::in_process, netId);
            startValidation(server, netId, false);
            startValidation(identity, netId, false);
        }
    }

@@ -128,9 +128,11 @@ PrivateDnsStatus PrivateDnsConfiguration::getStatus(unsigned netId) const {
    const auto netPair = mPrivateDnsTransports.find(netId);
    if (netPair != mPrivateDnsTransports.end()) {
        for (const auto& [_, server] : netPair->second) {
            if (server.active()) {
                status.serversMap.emplace(server, server.validationState());
            if (server->isDot() && server->active()) {
                DnsTlsServer& dotServer = *static_cast<DnsTlsServer*>(server.get());
                status.serversMap.emplace(dotServer, server->validationState());
            }
            // TODO: also add DoH server to the map.
        }
    }

@@ -145,7 +147,7 @@ void PrivateDnsConfiguration::clear(unsigned netId) {
}

base::Result<void> PrivateDnsConfiguration::requestValidation(unsigned netId,
                                                              const DnsTlsServer& server,
                                                              const ServerIdentity& identity,
                                                              uint32_t mark) {
    std::lock_guard guard(mPrivateDnsLock);

@@ -159,40 +161,39 @@ base::Result<void> PrivateDnsConfiguration::requestValidation(unsigned netId,
        return Errorf("Private DNS setting is not opportunistic mode");
    }

    auto netPair = mPrivateDnsTransports.find(netId);
    if (netPair == mPrivateDnsTransports.end()) {
        return Errorf("NetId not found in mPrivateDnsTransports");
    auto result = getPrivateDnsLocked(identity, netId);
    if (!result.ok()) {
        return result.error();
    }

    auto& tracker = netPair->second;
    const ServerIdentity identity = ServerIdentity(server);
    auto it = tracker.find(identity);
    if (it == tracker.end()) {
        return Errorf("Server was removed");
    }
    const IPrivateDnsServer* server = result.value();

    const DnsTlsServer& target = it->second;
    if (!server->active()) return Errorf("Server is not active");

    if (!target.active()) return Errorf("Server is not active");

    if (target.validationState() != Validation::success) {
    if (server->validationState() != Validation::success) {
        return Errorf("Server validation state mismatched");
    }

    // Don't run the validation if |mark| (from android_net_context.dns_mark) is different.
    // This is to protect validation from running on unexpected marks.
    // Validation should be associated with a mark gotten by system permission.
    if (target.mark != mark) return Errorf("Socket mark mismatched");
    if (server->validationMark() != mark) return Errorf("Socket mark mismatched");

    updateServerState(identity, Validation::in_process, netId);
    startValidation(target, netId, true);
    startValidation(identity, netId, true);
    return {};
}

void PrivateDnsConfiguration::startValidation(const DnsTlsServer& server, unsigned netId,
                                              bool isRevalidation) REQUIRES(mPrivateDnsLock) {
    // Note that capturing |server|, |netId|, and |isRevalidation| in this lambda create copies.
    std::thread validate_thread([this, server, netId, isRevalidation] {
void PrivateDnsConfiguration::startValidation(const ServerIdentity& identity, unsigned netId,
                                              bool isRevalidation) {
    // This ensures that the thread sends probe at least once in case
    // the server is removed before the thread starts running.
    // TODO: consider moving these code to the thread.
    const auto result = getPrivateDnsLocked(identity, netId);
    if (!result.ok()) return;
    DnsTlsServer server = *static_cast<const DnsTlsServer*>(result.value());

    std::thread validate_thread([this, identity, server, netId, isRevalidation] {
        setThreadName(StringPrintf("TlsVerify_%u", netId).c_str());

        // cat /proc/sys/net/ipv4/tcp_syn_retries yields "6".
@@ -217,13 +218,13 @@ void PrivateDnsConfiguration::startValidation(const DnsTlsServer& server, unsign
            // ::validate() is a blocking call that performs network operations.
            // It can take milliseconds to minutes, up to the SYN retry limit.
            LOG(WARNING) << "Validating DnsTlsServer " << server.toIpString() << " with mark 0x"
                         << std::hex << server.mark;
            const bool success = DnsTlsTransport::validate(server, server.mark);
                         << std::hex << server.validationMark();
            const bool success = DnsTlsTransport::validate(server, server.validationMark());
            LOG(WARNING) << "validateDnsTlsServer returned " << success << " for "
                         << server.toIpString();

            const bool needs_reeval =
                    this->recordPrivateDnsValidation(server, netId, success, isRevalidation);
                    this->recordPrivateDnsValidation(identity, netId, success, isRevalidation);

            if (!needs_reeval) {
                break;
@@ -240,11 +241,11 @@ void PrivateDnsConfiguration::startValidation(const DnsTlsServer& server, unsign
    validate_thread.detach();
}

void PrivateDnsConfiguration::sendPrivateDnsValidationEvent(const DnsTlsServer& server,
void PrivateDnsConfiguration::sendPrivateDnsValidationEvent(const ServerIdentity& identity,
                                                            unsigned netId, bool success) {
    LOG(DEBUG) << "Sending validation " << (success ? "success" : "failure") << " event on netId "
               << netId << " for " << server.toIpString() << " with hostname {" << server.name
               << "}";
               << netId << " for " << identity.sockaddr.ip().toString() << " with hostname {"
               << identity.provider << "}";
    // Send a validation event to NetdEventListenerService.
    const auto& listeners = ResolverEventReporter::getInstance().getListeners();
    if (listeners.empty()) {
@@ -252,15 +253,16 @@ void PrivateDnsConfiguration::sendPrivateDnsValidationEvent(const DnsTlsServer&
                << "Validation event not sent since no INetdEventListener receiver is available.";
    }
    for (const auto& it : listeners) {
        it->onPrivateDnsValidationEvent(netId, server.toIpString(), server.name, success);
        it->onPrivateDnsValidationEvent(netId, identity.sockaddr.ip().toString(), identity.provider,
                                        success);
    }

    // Send a validation event to unsolicited event listeners.
    const auto& unsolEventListeners = ResolverEventReporter::getInstance().getUnsolEventListeners();
    const PrivateDnsValidationEventParcel validationEvent = {
            .netId = static_cast<int32_t>(netId),
            .ipAddress = server.toIpString(),
            .hostname = server.name,
            .ipAddress = identity.sockaddr.ip().toString(),
            .hostname = identity.provider,
            .validation = success ? IDnsResolverUnsolicitedEventListener::VALIDATION_RESULT_SUCCESS
                                  : IDnsResolverUnsolicitedEventListener::VALIDATION_RESULT_FAILURE,
    };
@@ -269,11 +271,11 @@ void PrivateDnsConfiguration::sendPrivateDnsValidationEvent(const DnsTlsServer&
    }
}

bool PrivateDnsConfiguration::recordPrivateDnsValidation(const DnsTlsServer& server, unsigned netId,
                                                         bool success, bool isRevalidation) {
bool PrivateDnsConfiguration::recordPrivateDnsValidation(const ServerIdentity& identity,
                                                         unsigned netId, bool success,
                                                         bool isRevalidation) {
    constexpr bool NEEDS_REEVALUATION = true;
    constexpr bool DONT_REEVALUATE = false;
    const ServerIdentity identity = ServerIdentity(server);

    std::lock_guard guard(mPrivateDnsLock);

@@ -303,23 +305,19 @@ bool PrivateDnsConfiguration::recordPrivateDnsValidation(const DnsTlsServer& ser
    auto& tracker = netPair->second;
    auto serverPair = tracker.find(identity);
    if (serverPair == tracker.end()) {
        LOG(WARNING) << "Server " << server.toIpString()
        LOG(WARNING) << "Server " << identity.sockaddr.ip().toString()
                     << " was removed during private DNS validation";
        success = false;
        reevaluationStatus = DONT_REEVALUATE;
    } else if (!(serverPair->second == server)) {
        LOG(WARNING) << "Server " << server.toIpString()
                     << " was changed during private DNS validation";
        success = false;
        reevaluationStatus = DONT_REEVALUATE;
    } else if (!serverPair->second.active()) {
        LOG(WARNING) << "Server " << server.toIpString() << " was removed from the configuration";
    } else if (!serverPair->second->active()) {
        LOG(WARNING) << "Server " << identity.sockaddr.ip().toString()
                     << " was removed from the configuration";
        success = false;
        reevaluationStatus = DONT_REEVALUATE;
    }

    // Send private dns validation result to listeners.
    sendPrivateDnsValidationEvent(server, netId, success);
    sendPrivateDnsValidationEvent(identity, netId, success);

    if (success) {
        updateServerState(identity, Validation::success, netId);
@@ -338,26 +336,22 @@ bool PrivateDnsConfiguration::recordPrivateDnsValidation(const DnsTlsServer& ser

void PrivateDnsConfiguration::updateServerState(const ServerIdentity& identity, Validation state,
                                                uint32_t netId) {
    auto netPair = mPrivateDnsTransports.find(netId);
    if (netPair == mPrivateDnsTransports.end()) {
    const auto result = getPrivateDnsLocked(identity, netId);
    if (!result.ok()) {
        notifyValidationStateUpdate(identity.sockaddr, Validation::fail, netId);
        return;
    }

    auto& tracker = netPair->second;
    if (tracker.find(identity) == tracker.end()) {
        notifyValidationStateUpdate(identity.sockaddr, Validation::fail, netId);
        return;
    }
    auto* server = result.value();

    tracker[identity].setValidationState(state);
    server->setValidationState(state);
    notifyValidationStateUpdate(identity.sockaddr, state, netId);

    RecordEntry record(netId, identity, state);
    mPrivateDnsLog.push(std::move(record));
}

bool PrivateDnsConfiguration::needsValidation(const DnsTlsServer& server) {
bool PrivateDnsConfiguration::needsValidation(const IPrivateDnsServer& server) const {
    // The server is not expected to be used on the network.
    if (!server.active()) return false;

@@ -373,6 +367,28 @@ bool PrivateDnsConfiguration::needsValidation(const DnsTlsServer& server) {
    return false;
}

base::Result<IPrivateDnsServer*> PrivateDnsConfiguration::getPrivateDns(
        const ServerIdentity& identity, unsigned netId) {
    std::lock_guard guard(mPrivateDnsLock);
    return getPrivateDnsLocked(identity, netId);
}

base::Result<IPrivateDnsServer*> PrivateDnsConfiguration::getPrivateDnsLocked(
        const ServerIdentity& identity, unsigned netId) {
    auto netPair = mPrivateDnsTransports.find(netId);
    if (netPair == mPrivateDnsTransports.end()) {
        return Errorf("Failed to get private DNS: netId {} not found", netId);
    }

    auto iter = netPair->second.find(identity);
    if (iter == netPair->second.end()) {
        return Errorf("Failed to get private DNS: server {{{}/{}}} not found", identity.sockaddr,
                      identity.provider);
    }

    return iter->second.get();
}

void PrivateDnsConfiguration::setObserver(PrivateDnsValidationObserver* observer) {
    std::lock_guard guard(mPrivateDnsLock);
    mObserver = observer;
Loading