Below is the code snippet for SSL context initialization and verify callback registered. If I connect SSL client with proper certificates it verifies the certificate and works as expected.
But if I connect client without any certificate then it allows connection(actually it should not allow connection without certificates). If SSL client do not send certificate then it do not call verify callback.
boost::asio::ssl::context_base::method SSL_version =
static_cast<boost::asio::ssl::context_base::method>(param_values[ID_PROTOCOL_VERSION].int32_value);
// load certificate files
boost::shared_ptr<boost::asio::ssl::context> context_ = boost::shared_ptr<boost::asio::ssl::context>(
new boost::asio::ssl::context(SSL_version)); // parasoft-suppress BD-RES-LEAKS "The memory is allocated via boost::shared_ptr, hence it'll be deallocated automatically"
p_ctx = boost::static_pointer_cast<void>(context_);
context_->set_options(boost::asio::ssl::context::default_workarounds);
context_->use_certificate_chain_file(cert_chain_file);
context_->use_certificate_file(cert_file, boost::asio::ssl::context::pem);
context_->use_private_key_file(cert_file, boost::asio::ssl::context::pem);
context_->set_verify_mode(boost::asio::ssl::verify_peer);
context_->set_verify_callback(boost::bind(&verify_certificate_cb, _1, _2));
verify_certificate_cb
callback function
bool verify_certificate_cb(bool preverified, boost::asio::ssl::verify_context& ctx)
{
std::cout << "Function : " << __func__ << " ----------------- Line : " << __LINE__ << std::endl;
int8_t subject_name[256];
X509_STORE_CTX *cts = ctx.native_handle();
int32_t length = 0;
X509* cert = X509_STORE_CTX_get_current_cert(ctx.native_handle());
std::cout << "CTX ERROR : " << cts->error << std::endl;
int32_t depth = X509_STORE_CTX_get_error_depth(cts);
std::cout << "CTX DEPTH : " << depth << std::endl;
switch (cts->error)
{
case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
Debug(PRIORITY_ERROR, "X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT");
break;
case X509_V_ERR_CERT_NOT_YET_VALID:
case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
Debug(PRIORITY_ERROR, "Certificate not yet valid!!");
break;
case X509_V_ERR_CERT_HAS_EXPIRED:
case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
Debug(PRIORITY_ERROR, "Certificate expired..");
break;
case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
Debug(PRIORITY_WARN, "Self signed certificate in chain!!!\n");
preverified = true;
break;
default:
break;
}
const int32_t name_length = 256;
X509_NAME_oneline(X509_get_subject_name(cert), reinterpret_cast<char*>(subject_name), name_length);
Debug(PRIORITY_INFO, "Verifying %s", subject_name);
Debug(PRIORITY_INFO, "Verification status : %d", preverified);
std::cout << "Function : " << __func__ << " ----------------- Line : " << __LINE__ << std::endl;
return preverified;
}
How can I modify the code that do not allow connection without proper certificate files? Thanks in advance.!
Finally got the solution. One of my teammate has suggested to use flag boost::asio::ssl::verify_fail_if_no_peer_cert
in association with boost::asio::ssl::verify_peer
and it worked.
updated line of code :
context_->set_verify_mode(boost::asio::ssl::verify_peer | boost::asio::ssl::verify_fail_if_no_peer_cert);