summaryrefslogtreecommitdiff
path: root/jstests/ssl/ssl_count_protocols.js
blob: a9e3202c30f69f72d74a7d5f3ff377887eccded2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
// Ensure the server counts the server TLS versions used
(function() {
    'use strict';

    load("jstests/ssl/libs/ssl_helpers.js");

    var SERVER_CERT = "jstests/libs/server.pem";
    var CLIENT_CERT = "jstests/libs/client.pem";
    var CA_CERT = "jstests/libs/ca.pem";

    const protocols = ["TLS1_0", "TLS1_1", "TLS1_2", "TLS1_3"];

    // First, figure out what protocol our local TLS stack wants to speak.
    // We're going to observe a connection of this type from the testrunner.
    const expectedDefaultProtocol = detectDefaultTLSProtocol();
    print("Expected default protocol: " + expectedDefaultProtocol);

    function runTestWithoutSubset(client) {
        print("Running test: " + client);
        let disabledProtocols = protocols.slice();
        let expectedCounts = [0, 0, 0, 0, 0];
        expectedCounts[protocols.indexOf(expectedDefaultProtocol)] = 1;
        var index = disabledProtocols.indexOf(client);
        disabledProtocols.splice(index, 1);
        expectedCounts[index] += 1;
        print(tojson(expectedCounts));

        const conn = MongoRunner.runMongod({
            sslMode: 'allowSSL',
            sslPEMKeyFile: SERVER_CERT,
            sslDisabledProtocols: 'none',
            useLogFiles: true,
            tlsLogVersions: "TLS1_0,TLS1_1,TLS1_2,TLS1_3",
        });

        print(disabledProtocols);
        const version_number = client.replace(/TLS/, "").replace(/_/, ".");

        const exitStatus =
            runMongoProgram('mongo',
                            '--ssl',
                            '--sslAllowInvalidHostnames',
                            '--sslPEMKeyFile',
                            CLIENT_CERT,
                            '--sslCAFile',
                            CA_CERT,
                            '--port',
                            conn.port,
                            '--sslDisabledProtocols',
                            disabledProtocols.join(","),
                            '--eval',
                            // The Javascript string "1.0" is implicitly converted to the Number(1)
                            // Workaround this with parseFloat
                            'one = Number.parseFloat(1).toPrecision(2); a = {};' +
                                'a[one] = NumberLong(' + expectedCounts[0] + ');' +
                                'a["1.1"] = NumberLong(' + expectedCounts[1] + ');' +
                                'a["1.2"] = NumberLong(' + expectedCounts[2] + ');' +
                                'a["1.3"] = NumberLong(' + expectedCounts[3] + ');' +
                                'a["unknown"] = NumberLong(' + expectedCounts[4] + ');' +
                                'assert.eq(db.serverStatus().transportSecurity, a);');

        if (expectedDefaultProtocol === "TLS1_2" && client === "TLS1_3") {
            // If the runtime environment does not support TLS 1.3, a client cannot connect to a
            // server if TLS 1.3 is its only usable protocol version.
            assert.neq(
                0,
                exitStatus,
                "A client which does not support TLS 1.3 should not be able to connect with it");
            MongoRunner.stopMongod(conn);
            return;
        }

        assert.eq(0, exitStatus, "");

        print(`Checking ${conn.fullOptions.logFile} for TLS version message`);
        const log = cat(conn.fullOptions.logFile);

        // Find the last line in the log file and verify it has the right version
        let re = /Accepted connection with TLS Version (1\.\d) from connection 127.0.0.1:\d+/g;
        let result = re.exec(log);
        let lastResult = null;
        while (result !== null) {
            lastResult = result;
            result = re.exec(log);
        }

        assert(lastResult !== null,
               "'Accepted connection with TLS Version' log line missing in log file!\n" +
                   "Log file contents: " + conn.fullOptions.logFile +
                   "\n************************************************************\n" + log +
                   "\n************************************************************");

        assert.eq(lastResult['1'], version_number);

        MongoRunner.stopMongod(conn);
    }

    runTestWithoutSubset("TLS1_0");
    runTestWithoutSubset("TLS1_1");
    runTestWithoutSubset("TLS1_2");
    runTestWithoutSubset("TLS1_3");

})();