| 110 | }; |
| 111 | |
| 112 | void runTlsTest(int serverChainLen, int clientChainLen) { |
| 113 | log("==== BEGIN TESTCASE ===="); |
| 114 | auto clientSsl = ssl::context(ssl::context::tls); |
| 115 | auto serverSsl = ssl::context(ssl::context::tls); |
| 116 | auto const expectHandshakeOk = clientChainLen >= 0 && serverChainLen > 0; |
| 117 | auto const expectTrusted = clientChainLen != 0; |
| 118 | log("cert chain length: server {}, client {}", serverChainLen, clientChainLen); |
| 119 | auto arena = Arena(); |
| 120 | auto serverChain = mkcert::CertChainRef{}; |
| 121 | auto clientChain = mkcert::CertChainRef{}; |
| 122 | if (serverChainLen) { |
| 123 | auto tmpArena = Arena(); |
| 124 | auto specs = mkcert::makeCertChainSpec(tmpArena, std::labs(serverChainLen), mkcert::ESide::Server); |
| 125 | if (serverChainLen < 0) { |
| 126 | specs[0].offsetNotBefore = -60l * 60 * 24 * 365; |
| 127 | specs[0].offsetNotAfter = -10l; // cert that expired 10 seconds ago |
| 128 | } |
| 129 | serverChain = mkcert::makeCertChain(arena, specs, {} /* create root CA cert from spec*/); |
| 130 | } |
| 131 | if (clientChainLen) { |
| 132 | auto tmpArena = Arena(); |
| 133 | auto specs = mkcert::makeCertChainSpec(tmpArena, std::labs(clientChainLen), mkcert::ESide::Client); |
| 134 | if (clientChainLen < 0) { |
| 135 | specs[0].offsetNotBefore = -60l * 60 * 24 * 365; |
| 136 | specs[0].offsetNotAfter = -10l; // cert that expired 10 seconds ago |
| 137 | } |
| 138 | clientChain = mkcert::makeCertChain(arena, specs, {} /* create root CA cert from spec*/); |
| 139 | } |
| 140 | initSslContext(clientSsl, clientChain, serverChain, mkcert::ESide::Client); |
| 141 | log("client SSL contexts initialized"); |
| 142 | initSslContext(serverSsl, serverChain, clientChain, mkcert::ESide::Server); |
| 143 | log("server SSL contexts initialized"); |
| 144 | auto io = io_context(); |
| 145 | auto serverWorkGuard = work_guard_type(io.get_executor()); |
| 146 | auto clientWorkGuard = work_guard_type(io.get_executor()); |
| 147 | auto const ip = ip::address::from_string("127.0.0.1"); |
| 148 | auto acceptor = tcp::acceptor(io, tcp::endpoint(ip, 0)); |
| 149 | auto const serverAddr = acceptor.local_endpoint(); |
| 150 | logs("server listening at {}", serverAddr); |
| 151 | auto serverSock = tcp::socket(io); |
| 152 | auto serverSslSock = socket_type(serverSock, serverSsl); |
| 153 | enum class ESockState { AssumedUntrusted, Trusted }; |
| 154 | auto serverSockState = ESockState::AssumedUntrusted; |
| 155 | auto clientSockState = ESockState::AssumedUntrusted; |
| 156 | auto handshakeOk = true; |
| 157 | serverSslSock.set_verify_callback([&serverSockState, &handshakeOk](bool preverify, ssl::verify_context&) { |
| 158 | logs("client preverify: {}", preverify); |
| 159 | switch (serverSockState) { |
| 160 | case ESockState::AssumedUntrusted: |
| 161 | if (!preverify) |
| 162 | return handshakeOk = false; |
| 163 | serverSockState = ESockState::Trusted; |
| 164 | break; |
| 165 | case ESockState::Trusted: |
| 166 | if (!preverify) |
| 167 | return handshakeOk = false; |
| 168 | break; |
| 169 | default: |
no test coverage detected