unsigned char client_random[SSL3_RANDOM_SIZE];
unsigned char server_random[SSL3_RANDOM_SIZE];
#endif
+
+ int (*validate_ca_cb)(int ok_so_far, X509* cert, void *ca_ctx);
+ void *validate_ca_ctx;
};
return context;
}
-
#ifdef CONFIG_NO_STDOUT_DEBUG
static void _tls_show_errors(void)
else if (depth == 2)
conn->peer_issuer_issuer = err_cert;
+ wpa_printf(MSG_DEBUG, "TLS: tls_verify_cb(enter) - preverify_ok=%d "
+ "err=%d (%s) ca_cert_verify=%d depth=%d buf='%s'",
+ preverify_ok, err, X509_verify_cert_error_string(err),
+ conn->ca_cert_verify, depth, buf);
+
+
context = conn->context;
match = conn->subject_match;
altmatch = conn->altsubject_match;
suffix_match = conn->suffix_match;
domain_match = conn->domain_match;
- if (!preverify_ok && !conn->ca_cert_verify)
- preverify_ok = 1;
- if (!preverify_ok && depth > 0 && conn->server_cert_only)
+ if (!preverify_ok && !conn->ca_cert_verify) {
+ if (conn->validate_ca_cb) {
+ preverify_ok = conn->validate_ca_cb(preverify_ok, err_cert, conn->validate_ca_ctx);
+ wpa_printf(MSG_DEBUG, "TLS: tls_verify_cb: validate_ca_cb returned %d", preverify_ok);
+ }
+ else {
+ preverify_ok = 1;
+ wpa_printf(MSG_DEBUG, "TLS: tls_verify_cb: allowing cert because !conn->ca_cert_verify\n");
+ }
+ }
+ if (!preverify_ok && depth > 0 && conn->server_cert_only) {
+ wpa_printf(MSG_DEBUG, "TLS: tls_verify_cb: allowing cert because depth > 0 && conn->server_cert_only\n");
preverify_ok = 1;
+ }
if (!preverify_ok && (conn->flags & TLS_CONN_DISABLE_TIME_CHECKS) &&
(err == X509_V_ERR_CERT_HAS_EXPIRED ||
err == X509_V_ERR_CERT_NOT_YET_VALID)) {
- wpa_printf(MSG_DEBUG, "OpenSSL: Ignore certificate validity "
+ wpa_printf(MSG_DEBUG, "tls_verify_cb: OpenSSL: Ignore certificate validity "
"time mismatch");
preverify_ok = 1;
}
struct wpabuf *cert;
cert = get_x509_cert(err_cert);
if (!cert) {
- wpa_printf(MSG_DEBUG, "OpenSSL: Could not fetch "
+ wpa_printf(MSG_DEBUG, "tls_verify_cb: OpenSSL: Could not fetch "
"server certificate data");
preverify_ok = 0;
} else {
* regardless of other problems.
*/
wpa_printf(MSG_DEBUG,
- "OpenSSL: Ignore validation issues for a pinned server certificate");
+ "tls_verify_cb: OpenSSL: Ignore validation issues for a pinned server certificate");
preverify_ok = 1;
}
wpabuf_free(cert);
#endif /* CONFIG_SHA256 */
if (!preverify_ok) {
- wpa_printf(MSG_WARNING, "TLS: Certificate verification failed,"
+ wpa_printf(MSG_WARNING, "tls_verify_cb: TLS: Certificate verification failed,"
" error %d (%s) depth %d for '%s'", err, err_str,
depth, buf);
openssl_tls_fail_event(conn, err_cert, err, depth, buf,
return preverify_ok;
}
- wpa_printf(MSG_DEBUG, "TLS: tls_verify_cb - preverify_ok=%d "
+ wpa_printf(MSG_DEBUG, "TLS: tls_verify_cb(exit) - preverify_ok=%d "
"err=%d (%s) ca_cert_verify=%d depth=%d buf='%s'",
preverify_ok, err, err_str,
conn->ca_cert_verify, depth, buf);
if (depth == 0 && match && os_strstr(buf, match) == NULL) {
- wpa_printf(MSG_WARNING, "TLS: Subject '%s' did not "
+ wpa_printf(MSG_WARNING, "tls_verify_cb: TLS: Subject '%s' did not "
"match with '%s'", buf, match);
preverify_ok = 0;
openssl_tls_fail_event(conn, err_cert, err, depth, buf,
TLS_FAIL_SUBJECT_MISMATCH);
} else if (depth == 0 && altmatch &&
!tls_match_altsubject(err_cert, altmatch)) {
- wpa_printf(MSG_WARNING, "TLS: altSubjectName match "
+ wpa_printf(MSG_WARNING, "tls_verify_cb: TLS: altSubjectName match "
"'%s' not found", altmatch);
preverify_ok = 0;
openssl_tls_fail_event(conn, err_cert, err, depth, buf,
TLS_FAIL_ALTSUBJECT_MISMATCH);
} else if (depth == 0 && suffix_match &&
!tls_match_suffix(err_cert, suffix_match, 0)) {
- wpa_printf(MSG_WARNING, "TLS: Domain suffix match '%s' not found",
+ wpa_printf(MSG_WARNING, "tls_verify_cb: TLS: Domain suffix match '%s' not found",
suffix_match);
preverify_ok = 0;
openssl_tls_fail_event(conn, err_cert, err, depth, buf,
TLS_FAIL_DOMAIN_SUFFIX_MISMATCH);
} else if (depth == 0 && domain_match &&
!tls_match_suffix(err_cert, domain_match, 1)) {
- wpa_printf(MSG_WARNING, "TLS: Domain match '%s' not found",
+ wpa_printf(MSG_WARNING, "tls_verify_cb: TLS: Domain match '%s' not found",
domain_match);
preverify_ok = 0;
openssl_tls_fail_event(conn, err_cert, err, depth, buf,
openssl_tls_cert_event(conn, err_cert, depth, buf);
if (conn->cert_probe && preverify_ok && depth == 0) {
- wpa_printf(MSG_DEBUG, "OpenSSL: Reject server certificate "
+ wpa_printf(MSG_DEBUG, "tls_verify_cb: OpenSSL: Reject server certificate "
"on probe-only run");
preverify_ok = 0;
openssl_tls_fail_event(conn, err_cert, err, depth, buf,
static int tls_connection_ca_cert(struct tls_data *data,
- struct tls_connection *conn,
- const char *ca_cert, const u8 *ca_cert_blob,
- size_t ca_cert_blob_len, const char *ca_path)
+ struct tls_connection *conn,
+ const char *ca_cert, const u8 *ca_cert_blob,
+ size_t ca_cert_blob_len, const char *ca_path,
+ int (*validate_ca_cb)(int ok_so_far, X509* cert, void *ca_ctx),
+ void *validate_ca_ctx)
{
SSL_CTX *ssl_ctx = data->ssl;
X509_STORE *store;
if (ca_cert && os_strncmp(ca_cert, "probe://", 8) == 0) {
wpa_printf(MSG_DEBUG, "OpenSSL: Probe for server certificate "
- "chain");
+ "chain; setting conn->ca_cert_verify=0");
conn->cert_probe = 1;
conn->ca_cert_verify = 0;
return 0;
} else {
/* No ca_cert configured - do not try to verify server
* certificate */
+ wpa_printf(MSG_DEBUG, "OpenSSL: tls_connection_ca_cert: No ca_cert; setting conn->ca_cert_verify=0");
conn->ca_cert_verify = 0;
+ conn->validate_ca_cb = validate_ca_cb;
+ conn->validate_ca_ctx = validate_ca_ctx;
}
return 0;
SSL_VERIFY_FAIL_IF_NO_PEER_CERT |
SSL_VERIFY_CLIENT_ONCE, tls_verify_cb);
} else {
+ wpa_printf(MSG_DEBUG, "OpenSSL: tls_connection_set_verify: !verify_peer; setting conn->ca_cert_verify=0");
conn->ca_cert_verify = 0;
SSL_set_verify(conn->ssl, SSL_VERIFY_NONE, NULL);
}
if (engine_id && ca_cert_id) {
if (tls_connection_engine_ca_cert(data, conn, ca_cert_id))
return TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED;
- } else if (tls_connection_ca_cert(data, conn, params->ca_cert,
- params->ca_cert_blob,
- params->ca_cert_blob_len,
- params->ca_path))
- return -1;
+ } else {
+ if (tls_connection_ca_cert(data, conn, params->ca_cert,
+ params->ca_cert_blob,
+ params->ca_cert_blob_len,
+ params->ca_path, params->validate_ca_cb,
+ params->validate_ca_ctx))
+ return -1;
+ }
if (engine_id && cert_id) {
if (tls_connection_engine_client_cert(conn, cert_id))