mem = BIO_new(BIO_s_mem());
if (!mem)
return;
- X509_NAME_print_ex(mem, X509_get_subject_name(cert), 4,
+ X509_NAME_print_ex(mem, X509_get_subject_name(cert), 0,
XN_FLAG_ONELINE);
- X509_NAME_print_ex(mem, X509_get_issuer_name(cert), 4, XN_FLAG_ONELINE);
+ X509_NAME_print_ex(mem, X509_get_issuer_name(cert), 2, XN_FLAG_ONELINE);
if (BIO_write(mem, "", 1) == 1) {
len = BIO_get_mem_data(mem, &memptr);
if (memptr && len > 0)
- Log(level, "%s: \"%s\"", msg, memptr);
+ Log(level, "%s: \"%s\".", msg, memptr);
}
(void)BIO_set_close(mem, BIO_CLOSE);
BIO_free(mem);
static int
Verify_openssl(int preverify_ok, X509_STORE_CTX * ctx)
{
- int err;
-
+#ifdef DEBUG
if (!preverify_ok) {
- err = X509_STORE_CTX_get_error(ctx);
- Log(LOG_ERR, "Certificate validation failed: %s",
- X509_verify_cert_error_string(err));
+ int err = X509_STORE_CTX_get_error(ctx);
+ LogDebug("Certificate validation failed: %s",
+ X509_verify_cert_error_string(err));
}
- return preverify_ok;
+#else
+ (void)preverify_ok;
+ (void)ctx;
+#endif
+
+ /* Always(!) return success as we have to deal with invalid
+ * (self-signed, expired, ...) client certificates and with invalid
+ * server certificates when "SSLVerify" is disabled, which we don't
+ * know at this stage. Therefore we postpone this check, it will be
+ * (and has to be!) handled in cb_connserver_login_ssl(). */
+ return 1;
}
#endif
SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 |
SSL_OP_NO_COMPRESSION);
SSL_CTX_set_mode(newctx, SSL_MODE_ENABLE_PARTIAL_WRITE);
- SSL_CTX_set_verify(newctx, SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE,
- Verify_openssl);
SSL_CTX_free(ssl_ctx);
ssl_ctx = newctx;
Log(LOG_INFO, "%s initialized.", OpenSSL_version(OPENSSL_VERSION));
{
X509_STORE *store = NULL;
X509_LOOKUP *lookup;
- int verify_flags = SSL_VERIFY_PEER;
bool ret = false;
if (!Conf_SSLOptions.CAFile)
}
}
- SSL_CTX_set_verify(ctx, verify_flags, Verify_openssl);
+ SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE,
+ Verify_openssl);
SSL_CTX_set_verify_depth(ctx, MAX_CERT_CHAIN_LENGTH);
ret = true;
out:
if (!ret)
return false;
Conn_OPTION_ADD(c, CONN_SSL_CONNECT);
+
#ifdef HAVE_LIBSSL
assert(c->ssl_state.ssl);
- if (s->SSLVerify) {
- X509_VERIFY_PARAM *param = NULL;
- param = SSL_get0_param(c->ssl_state.ssl);
- X509_VERIFY_PARAM_set_hostflags(param,
- X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
- int err = X509_VERIFY_PARAM_set1_host(param, s->host, 0);
- if (err != 1) {
- Log(LOG_ERR,
- "Cannot set up hostname verification for '%s': %u",
- s->host, err);
- return false;
- }
+
+ X509_VERIFY_PARAM *param = SSL_get0_param(c->ssl_state.ssl);
+ X509_VERIFY_PARAM_set_hostflags(param, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
+ int err = X509_VERIFY_PARAM_set1_host(param, s->host, 0);
+ if (err != 1) {
+ Log(LOG_ERR,
+ "Cannot set up hostname verification for '%s': %u",
+ s->host, err);
+ return false;
+ }
+
+ if (s->SSLVerify)
SSL_set_verify(c->ssl_state.ssl, SSL_VERIFY_PEER,
Verify_openssl);
- } else
+ else
SSL_set_verify(c->ssl_state.ssl, SSL_VERIFY_NONE, NULL);
#endif
+
return true;
}
"SSL error, client disconnected [in %s()]!",
fname);
break;
- case -1: /* low level socket I/O error, check errno */
- Log(LOG_ERR, "SSL error: %s [in %s()]!",
- strerror(real_errno), fname);
+ case -1:
+ /* Low level socket I/O error, check errno. But
+ * we don't need to log this here, the generic
+ * connection layer will take care of it. */
+ LogDebug("SSL error: %s [in %s()]!",
+ strerror(real_errno), fname);
}
}
break;
Log(LOG_INFO, "Connection %d: initialized %s using cipher %s, %s.",
c->sock, SSL_get_version(ssl), SSL_get_cipher(ssl), comp_alg);
peer_cert = SSL_get_peer_certificate(ssl);
- if (peer_cert && connect) {
+ if (peer_cert) {
cert_seen = true;
- /* Client: Check server certificate */
- int err = SSL_get_verify_result(ssl);
- if (err == X509_V_OK) {
- const char *peername = SSL_get0_peername(ssl);
- if (peername != NULL)
- cert_ok = true;
- LogDebug("X509_V_OK, peername = '%s'", peername);
- } else
- Log(LOG_ERR, "Certificate validation failed: %s",
- X509_verify_cert_error_string(err));
- snprintf(msg, sizeof(msg), "%svalid peer certificate",
- cert_ok ? "" : "in");
- LogOpenSSL_CertInfo(cert_ok ? LOG_DEBUG : LOG_ERR, peer_cert,
- msg);
+
+ if (connect) {
+ /* Outgoing connection. Verify the remote server! */
+ int err = SSL_get_verify_result(ssl);
+ if (err == X509_V_OK) {
+ const char *peername = SSL_get0_peername(ssl);
+ if (peername != NULL)
+ cert_ok = true;
+ LogDebug("X509_V_OK, peername = '%s'", peername);
+ } else
+ Log(LOG_WARNING, "Certificate validation failed: %s!",
+ X509_verify_cert_error_string(err));
+
+ snprintf(msg, sizeof(msg), "Got %svalid server certificate",
+ cert_ok ? "" : "in");
+ LogOpenSSL_CertInfo(LOG_INFO, peer_cert, msg);
+ } else {
+ /* Incoming connection.
+ * Accept all certificates, don't depend on their
+ * validity: for example, we don't know the hostname
+ * to check, because we not yet even know if this is a
+ * server connection at all and if so, which one, so we
+ * don't know a host name to look for. On the other
+ * hand we want client certificates, for example for
+ * "CertFP" authentication with services ... */
+ LogOpenSSL_CertInfo(LOG_INFO, peer_cert,
+ "Got unchecked client certificate");
+ }
X509_free(peer_cert);
}
if (cert_ok)
Conn_OPTION_ADD(c, CONN_SSL_PEERCERT_OK);
if (!cert_seen)
- Log(LOG_INFO, "Peer did not present a certificate");
+ Log(LOG_INFO, "Peer did not present a certificate.");
}