|
|
|
|
@ -167,29 +167,43 @@ enum sslstatus MySQL_Data_Stream::do_ssl_handshake() {
|
|
|
|
|
int n = SSL_do_handshake(ssl);
|
|
|
|
|
if (n == 1) {
|
|
|
|
|
//proxy_info("SSL handshake completed\n");
|
|
|
|
|
long rc = SSL_get_verify_result(ssl);
|
|
|
|
|
if (rc != X509_V_OK && rc != X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN && rc != X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE) {
|
|
|
|
|
proxy_error("Disconnecting %s:%d: X509 client SSL certificate verify error: (%d:%s)\n" , addr.addr, addr.port, rc, X509_verify_cert_error_string(rc));
|
|
|
|
|
return SSLSTATUS_FAIL;
|
|
|
|
|
} else {
|
|
|
|
|
X509 *cert;
|
|
|
|
|
cert = SSL_get_peer_certificate(ssl);
|
|
|
|
|
if (cert) {
|
|
|
|
|
ASN1_STRING *str;
|
|
|
|
|
GENERAL_NAME *sanName;
|
|
|
|
|
STACK_OF(GENERAL_NAME) *san_names = NULL;
|
|
|
|
|
san_names = (stack_st_GENERAL_NAME *)X509_get_ext_d2i((X509 *) cert, NID_subject_alt_name, NULL, NULL);
|
|
|
|
|
if (san_names) {
|
|
|
|
|
sanName = sk_GENERAL_NAME_value(san_names, 0);
|
|
|
|
|
str = sanName->d.dNSName;
|
|
|
|
|
proxy_info("%s\n" , str->data);
|
|
|
|
|
x509_subject_alt_name = strdup((const char*)str->data);
|
|
|
|
|
X509 *cert;
|
|
|
|
|
cert = SSL_get_peer_certificate(ssl);
|
|
|
|
|
if (cert) {
|
|
|
|
|
GENERAL_NAMES *alt_names = (stack_st_GENERAL_NAME *)X509_get_ext_d2i((X509*)cert, NID_subject_alt_name, 0, 0);
|
|
|
|
|
int alt_name_count = sk_GENERAL_NAME_num(alt_names);
|
|
|
|
|
|
|
|
|
|
// Iterate all the SAN names, looking for SPIFFE identifier
|
|
|
|
|
for (int i = 0; i < alt_name_count; i++) {
|
|
|
|
|
GENERAL_NAME *san = sk_GENERAL_NAME_value(alt_names, i);
|
|
|
|
|
|
|
|
|
|
// We only care about URI names
|
|
|
|
|
if (san->type == GEN_URI) {
|
|
|
|
|
if (san->d.uniformResourceIdentifier->data) {
|
|
|
|
|
const char* resource_data =
|
|
|
|
|
reinterpret_cast<const char*>(san->d.uniformResourceIdentifier->data);
|
|
|
|
|
const char* spiffe_loc = strstr(resource_data, "spiffe");
|
|
|
|
|
|
|
|
|
|
// First name starting with 'spiffe' is considered the match.
|
|
|
|
|
if (spiffe_loc == resource_data) {
|
|
|
|
|
x509_subject_alt_name = strdup(resource_data);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// we currently disable this annoying error
|
|
|
|
|
// in future we can configure this as per user level, specifying if the certificate is mandatory or not
|
|
|
|
|
// see issue #3424
|
|
|
|
|
//proxy_error("X509 error: no required certificate sent by client\n");
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// we currently disable this annoying error
|
|
|
|
|
// in future we can configure this as per user level, specifying if the certificate is mandatory or not
|
|
|
|
|
// see issue #3424
|
|
|
|
|
//proxy_error("X509 error: no required certificate sent by client\n");
|
|
|
|
|
}
|
|
|
|
|
// In case the supplied certificate has a 'SAN'-'URI' identifier
|
|
|
|
|
// starting with 'spiffe', client certificate verification is performed.
|
|
|
|
|
if (x509_subject_alt_name != NULL) {
|
|
|
|
|
long rc = SSL_get_verify_result(ssl);
|
|
|
|
|
if (rc != X509_V_OK) {
|
|
|
|
|
proxy_error("Disconnecting %s:%d: X509 client SSL certificate verify error: (%d:%s)\n" , addr.addr, addr.port, rc, X509_verify_cert_error_string(rc));
|
|
|
|
|
return SSLSTATUS_FAIL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|