// // Copyright (c) 2019-2022 Ruben Perez Hidalgo (rubenperez038 at gmail dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // //[example_ssl #include #include #include #include #include #include #include #define ASSERT(expr) \ if (!(expr)) \ { \ std::cerr << "Assertion failed: " #expr << std::endl; \ exit(1); \ } // The CA file that signed the server's certificate constexpr const char CA_PEM[] = R"%(-----BEGIN CERTIFICATE----- MIIDZzCCAk+gAwIBAgIUWznm2UoxXw3j7HCcp9PpiayTvFQwDQYJKoZIhvcNAQEL BQAwQjELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxDjAMBgNVBAoM BW15c3FsMQ4wDAYDVQQDDAVteXNxbDAgFw0yMDA0MDQxNDMwMjNaGA8zMDE5MDgw NjE0MzAyM1owQjELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxDjAM BgNVBAoMBW15c3FsMQ4wDAYDVQQDDAVteXNxbDCCASIwDQYJKoZIhvcNAQEBBQAD ggEPADCCAQoCggEBAN0WYdvsDb+a0TxOGPejcwZT0zvTrf921mmDUlrLN1Z0hJ/S ydgQCSD7Q+6za4lTFZCXcvs52xvvS2gfC0yXyYLCT/jA4RQRxuF+/+w1gDWEbGk0 KzEpsBuKrEIvEaVdoS78SxInnW/aegshdrRRocp4JQ6KHsZgkLTxSwPfYSUmMUo0 cRO0Q/ak3VK8NP13A6ZFvZjrBxjS3cSw9HqilgADcyj1D4EokvfI1C9LrgwgLlZC XVkjjBqqoMXGGlnXOEK+pm8bU68HM/QvMBkb1Amo8pioNaaYgqJUCP0Ch0iu1nUU HtsWt6emXv0jANgIW0oga7xcT4MDGN/M+IRWLTECAwEAAaNTMFEwHQYDVR0OBBYE FNxhaGwf5ePPhzK7yOAKD3VF6wm2MB8GA1UdIwQYMBaAFNxhaGwf5ePPhzK7yOAK D3VF6wm2MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAAoeJCAX IDCFoAaZoQ1niI6Ac/cds8G8It0UCcFGSg+HrZ0YujJxWIruRCUG60Q2OAbEvn0+ uRpTm+4tV1Wt92WFeuRyqkomozx0g4CyfsxGX/x8mLhKPFK/7K9iTXM4/t+xQC4f J+iRmPVsMKQ8YsHYiWVhlOMH9XJQiqERCB2kOKJCH6xkaF2k0GbM2sGgbS7Z6lrd fsFTOIVx0VxLVsZnWX3byE9ghnDR5jn18u30Cpb/R/ShxNUGIHqRa4DkM5la6uZX W1fpSW11JBSUv4WnOO0C2rlIu7UJWOROqZZ0OsybPRGGwagcyff2qVRuI2XFvAMk OzBrmpfHEhF6NDU= -----END CERTIFICATE----- )%"; void print_employee(boost::mysql::row_view employee) { std::cout << "Employee '" << employee[0] << " " // first_name (string) << employee[1] << "' earns " // last_name (string) << employee[2] << " dollars yearly\n"; // salary (double) } void main_impl(int argc, char** argv) { if (argc != 4) { std::cerr << "Usage: " << argv[0] << " \n"; exit(1); } // I/O context boost::asio::io_context ctx; // Resolver for hostname resolution boost::asio::ip::tcp::resolver resolver(ctx.get_executor()); // Connection params boost::mysql::handshake_params params( argv[1], // username argv[2], // password "boost_mysql_examples" // database to use; leave empty or omit the parameter for no // database ); // This context will be used by the underlying SSL stream object. We can // set up here any SSL-related options, like peer verification or CA // certificates. We will do these in the next lines. boost::asio::ssl::context ssl_ctx(boost::asio::ssl::context::tls_client); // Check whether the server's certificate is valid and signed by a trusted CA. // If it's not, our handshake or connect operation will fail. ssl_ctx.set_verify_mode(boost::asio::ssl::verify_peer); // Load a trusted CA, which was used to sign the server's certificate. // This will allow the signature verification to succeed in our example. // You will have to run your MySQL server with the test certificates // located under $BOOST_MYSQL_ROOT/tools/ssl/ ssl_ctx.add_certificate_authority(boost::asio::buffer(CA_PEM)); // We expect the server certificate's common name to be "mysql". // If it's not, the certificate will be rejected and handshake or connect will fail. ssl_ctx.set_verify_callback(boost::asio::ssl::host_name_verification("mysql")); // Pass in our SSL context to the connection. Note that we // can create many connections out of a single context. We need to keep the // context alive until we finish using the connection. boost::mysql::tcp_ssl_connection conn(ctx, ssl_ctx); // Hostname resolution auto endpoints = resolver.resolve(argv[3], boost::mysql::default_port_string); // Connect to the server. This operation will perform the SSL handshake as part of // it, and thus will fail if the certificate is found to be invalid. conn.connect(*endpoints.begin(), params); // We can now use the connection as we would normally do. const char* sql = "SELECT first_name, last_name, salary FROM employee WHERE company_id = 'HGS'"; boost::mysql::tcp_ssl_resultset result; conn.query(sql, result); boost::mysql::rows employees; result.read_all(employees); for (const auto& employee : employees) { print_employee(employee); } // Cleanup conn.close(); } int main(int argc, char** argv) { try { main_impl(argc, argv); } catch (const boost::system::system_error& err) { std::cerr << "Error: " << err.what() << ", error code: " << err.code() << std::endl; return 1; } catch (const std::exception& err) { std::cerr << "Error: " << err.what() << std::endl; return 1; } } //]