CVE-2021-42073 (C++, published 2021-11-08T04:15Z)
Description: value: An issue was discovered in Barrier before 2.4.0. An attacker can enter an active session state with the barriers component (aka the server-side implementation of Barrier) simply by supplying a client label that identifies a valid client configuration. This label is "Unnamed" by default but could instead be guessed from hostnames or other publicly available information. In the active session state, an attacker can capture input device events from the server, and also modify the clipboard content on the server.
Severity: MEDIUM (CVSS v3 base score: 8.2)
Weakness: CWE-384 \u2014 Session Fixation
Authenticating a user, or otherwise establishing a new user session, without invalidating any existing session identifier gives an attacker the opportunity to steal authenticated sessions.
Repository: https://github.com/debauchee/barrier
Files changed:
doc/newsfragments/client-certificate-checking.bugfix
src/gui/src/MainWindow.cpp
src/lib/barrier/ArgParser.cpp
src/lib/barrier/ServerApp.cpp
src/lib/barrier/ServerArgs.h
src/lib/client/Client.cpp
src/lib/net/ConnectionSecurityLevel.h
src/lib/net/SecureSocket.cpp
Commit message: Implement client identity verification

This commit fixes two security vulnerabilities: CVE-2021-42072 and
CVE-2021-42073.

The issues have been reported by Matthias Gerstner <mgerstner@suse.de>.


Vulnerable code:
    QRegExp fingerprintRegex(".*server fingerprint \\(SHA1\\): ([A-F0-9:]+) \\(SHA256\\): ([A-F0-9:]+)");
    auto db_path = barrier::DataDirectories::trusted_servers_ssl_fingerprints_path();
        stopBarrier();
        messageBoxAlreadyShown = true;
        QMessageBox::StandardButton fingerprintReply =
            QMessageBox::information(
            this, tr("Security question"),
            tr("Do you trust this fingerprint?\n\n"
               "SHA1 (obsolete, when using old Barrier server):\n"
            .arg(QString::fromStdString(barrier::format_ssl_fingerprint(fingerprint_sha1.data))),
            startBarrier();
        else {
           << HELP_COMMON_INFO_1 << WINAPI_INFO << HELP_SYS_INFO << HELP_COMMON_INFO_2 << "\n"
        security_level = ConnectionSecurityLevel::ENCRYPTED;
    LOG((CLOG_NOTE "server fingerprint (SHA1): %s (SHA256): %s",

Fixed code:
SECURITY ISSUE

Barrier now supports client identity verification (fixes CVE-2021-42072, CVE-2021-42073).

To support seamless upgrades from older versions of Barrier this is currently disabled by default.
The feature can be enabled in the settings dialog. If enabled, older clients of Barrier will be
rejected.
    QRegExp fingerprintRegex(".*peer fingerprint \\(SHA1\\): ([A-F0-9:]+) \\(SHA256\\): ([A-F0-9:]+)");
    bool is_client = barrierType() == barrierClient;

    auto db_path = is_client
            ? barrier::DataDirectories::trusted_servers_ssl_fingerprints_path()
            : barrier::DataDirectories::trusted_clients_ssl_fingerprints_path();
        if (is_client) {
            stopBarrier();
        }
        QString message;
        if (is_client) {
            message = tr("Do you trust this fingerprint?\n\n"
               "SHA1 (obsolete, when using old Barrier client):\n"
            .arg(QString::fromStdString(barrier::format_ssl_fingerprint(fingerprint_sha1.data)));
        } else {
            message = tr("Do you trust this fingerprint?\n\n"
               "SHA256:\n"
               "%1\n"
               "%2\n\n"
               "This is a client fingerprint. You should compare this "
               "fingerprint to the one on your client's screen. If the "
               "two don't match exactly, then it's probably not the client "
               "you're expecting (it could be a malicious user).\n\n"
               "To automatically trust this fingerprint for future "
               "connections, click Yes. To reject this fingerprint and "
               "disconnect the client, click No.")
            .arg(QString::fromStdString(barrier::format_ssl_fingerprint(fingerprint_sha256.data)))
            .arg(QString::fromStdString(
                     barrier::create_fingerprint_randomart(fingerprint_sha256.data)));
        }

        messageBoxAlreadyShown = true;
        QMessageBox::StandardButton fingerprintReply =
            QMessageBox::information(
            this, tr("Security question"),
            message,
            if (is_client) {
                startBarrier();
            }
    if (!appConfig().getRequireClientCertificate()) {
        args << "--disable-client-cert-checking";
    }

        else if (isArg(i, argc, argv, nullptr, "--disable-client-cert-checking")) {
            args.check_client_certificates = false;
        } else {
           << HELP_COMMON_INFO_1
           << "      --disable-client-cert-checking disable client SSL certificate \n"
              "                                     checking (deprecated)\n"
           << WINAPI_INFO << HELP_SYS_INFO << HELP_COMMON_INFO_2 << "\n"
        if (args().check_client_certificates) {
            security_level = ConnectionSecurityLevel::ENCRYPTED_AUTHENTICATED;
        }
    bool check_client_certificates = true;
        // client always authenticates server
        security_level = ConnectionSecurityLevel::ENCRYPTED_AUTHENTICATED;
    ENCRYPTED_AUTHENTICATED
static int cert_verify_ignore_callback(X509_STORE_CTX*, void*)
{
    return 1;
}


    if (security_level_ == ConnectionSecurityLevel::ENCRYPTED_AUTHENTICATED) {
        // We want to ask for peer certificate, but not verify it. If we don't ask for peer
        // certificate, e.g. client won't send it.
        SSL_CTX_set_verify(m_ssl->m_context, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
                           nullptr);
        SSL_CTX_set_cert_verify_callback(m_ssl->m_context, cert_verify_ignore_callback, nullptr);
    }
        if (security_level_ == ConnectionSecurityLevel::ENCRYPTED_AUTHENTICATED) {
            if (verify_cert_fingerprint(
                        barrier::DataDirectories::trusted_clients_ssl_fingerprints_path())) {
                LOG((CLOG_INFO "accepted secure socket"));
                if (!ensure_peer_certificate()) {
                    retry = 0;
                    disconnect();
                    return -1;// Cert fail, error
                }
            }
            else {
                LOG((CLOG_ERR "failed to verify server certificate fingerprint"));
                retry = 0;
                disconnect();
                return -1; // Fingerprint failed, error
            }
        }

    LOG((CLOG_NOTE "peer fingerprint (SHA1): %s (SHA256): %s",