I wanted to use TLS on a regular socket file descriptor and could not find a single man-page or example explaining how to construct the BIO* that let me do cleartext BIO_read() and BIO_write() on a HTTPS socket.
After much experimenting, I finally figured it out. Making a note here for future reference.
// context is a smart pointer to a CTX* structure containing certs etc.
// server_fd is a plain TCP socket descriptor in "listen" mode
// returns client_fd that your application must close
// Use BIO_read() and BIO_write() to communicate with the client,
// you *MUST NOT* read/write on client_fd
int Socket::accept(const Context& context, int server_fd)
{
this->verify_flag = -1;
this->ssl = nullptr;
this->bio = nullptr;
// TCP accept
int client_fd = Net::accept(server_fd);
if (client_fd != -1) {
// TCP accept successful
// Create a BIO chain and get the SSL pointer
BIO* raw = BIO_new_socket(client_fd, BIO_NOCLOSE);
BIO* ssl = BIO_new_ssl(context.get(), 0); // 0=server, 1=client
this->bio = BIO_push(ssl, raw);
BIO_get_ssl(ssl, &this->ssl);
// SSL protocol accept
int rc = SSL_accept(this->ssl);
if (rc <= 0) {
// 0 = SSL failure, <0 = connection failure
report_error("SSL_accept...");
Net::close(client_fd);
client_fd = -1;
}
std::cout << "calling SSL_get_verify_result()" << std::endl;
this->verify_flag = SSL_get_verify_result(this->ssl);
}
return client_fd;
}