ssl: add LWS_CALLBACK_OPENSSL_PERFORM_SERVER_CERT_VERIFICATION
This commit is contained in:
parent
9e562fcf1b
commit
b837f93dcf
2 changed files with 93 additions and 4 deletions
|
@ -1016,6 +1016,36 @@ enum lws_callback_reasons {
|
|||
* From this callback, when you have sent everything, you should let
|
||||
* lws know by calling lws_client_http_body_pending(wsi, 0)
|
||||
*/
|
||||
LWS_CALLBACK_OPENSSL_PERFORM_SERVER_CERT_VERIFICATION = 58,
|
||||
/**< Similar to LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION
|
||||
* this callback is called during OpenSSL verification of the cert
|
||||
* sent from the server to the client. It is sent to protocol[0]
|
||||
* callback as no protocol has been negotiated on the connection yet.
|
||||
* Notice that the wsi is set because lws_client_connect_via_info was
|
||||
* successful.
|
||||
*
|
||||
* See http://www.openssl.org/docs/ssl/SSL_CTX_set_verify.html
|
||||
* to understand more detail about the OpenSSL callback that
|
||||
* generates this libwebsockets callback and the meanings of the
|
||||
* arguments passed. In this callback, user is the x509_ctx,
|
||||
* in is the ssl pointer and len is preverify_ok.
|
||||
*
|
||||
* THIS IS NOT RECOMMENDED BUT if a cert validation error shall be
|
||||
* overruled and cert shall be accepted as ok,
|
||||
* X509_STORE_CTX_set_error((X509_STORE_CTX*)user, X509_V_OK); must be
|
||||
* called and return value must be 0 to mean the cert is OK;
|
||||
* returning 1 will fail the cert in any case.
|
||||
*
|
||||
* This also means that if you don't handle this callback then
|
||||
* the default callback action of returning 0 will not accept the
|
||||
* certificate in case of a validation error decided by the SSL lib.
|
||||
*
|
||||
* This is expected and secure behaviour when validating certificates.
|
||||
*
|
||||
* Note: LCCSCF_ALLOW_SELFSIGNED and
|
||||
* LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK still work without this
|
||||
* callback being implemented.
|
||||
*/
|
||||
|
||||
/****** add new things just above ---^ ******/
|
||||
|
||||
|
|
|
@ -29,6 +29,64 @@ lws_ssl_bind_passphrase(SSL_CTX *ssl_ctx, struct lws_context_creation_info *info
|
|||
|
||||
extern int lws_ssl_get_error(struct lws *wsi, int n);
|
||||
|
||||
#if defined(LWS_USE_POLARSSL)
|
||||
#else
|
||||
#if defined(LWS_USE_MBEDTLS)
|
||||
#else
|
||||
#ifdef USE_WOLFSSL
|
||||
#else
|
||||
|
||||
static int
|
||||
OpenSSL_client_verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx)
|
||||
{
|
||||
SSL *ssl;
|
||||
int n;
|
||||
struct lws *wsi;
|
||||
|
||||
/* keep old behaviour accepting self-signed server certs */
|
||||
if (!preverify_ok) {
|
||||
int err = X509_STORE_CTX_get_error(x509_ctx);
|
||||
|
||||
if (err != X509_V_OK) {
|
||||
ssl = X509_STORE_CTX_get_ex_data(x509_ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
|
||||
wsi = SSL_get_ex_data(ssl, openssl_websocket_private_data_index);
|
||||
|
||||
if ((err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT ||
|
||||
err == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN) &&
|
||||
wsi->use_ssl & LCCSCF_ALLOW_SELFSIGNED) {
|
||||
lwsl_notice("accepting self-signed certificate\n");
|
||||
X509_STORE_CTX_set_error(x509_ctx, X509_V_OK);
|
||||
return 1; // ok
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ssl = X509_STORE_CTX_get_ex_data(x509_ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
|
||||
wsi = SSL_get_ex_data(ssl, openssl_websocket_private_data_index);
|
||||
|
||||
n = lws_get_context_protocol(wsi->context, 0).callback(wsi, LWS_CALLBACK_OPENSSL_PERFORM_SERVER_CERT_VERIFICATION, x509_ctx, ssl, preverify_ok);
|
||||
|
||||
/* keep old behaviour if something wrong with server certs */
|
||||
/* if ssl error is overruled in callback and cert is ok,
|
||||
* X509_STORE_CTX_set_error(x509_ctx, X509_V_OK); must be set and
|
||||
* return value is 0 from callback */
|
||||
if (!preverify_ok) {
|
||||
int err = X509_STORE_CTX_get_error(x509_ctx);
|
||||
|
||||
if (err != X509_V_OK) { /* cert validation error was not handled in callback */
|
||||
int depth = X509_STORE_CTX_get_error_depth(x509_ctx);
|
||||
const char* msg = X509_verify_cert_error_string(err);
|
||||
lwsl_err("SSL error: %s (preverify_ok=%d;err=%d;depth=%d)\n", msg, preverify_ok, err, depth);
|
||||
return preverify_ok; // not ok
|
||||
}
|
||||
}
|
||||
/* convert callback return code from 0 = OK to verify callback return value 1 = OK */
|
||||
return !n;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
int
|
||||
lws_ssl_client_bio_create(struct lws *wsi)
|
||||
{
|
||||
|
@ -37,7 +95,6 @@ lws_ssl_client_bio_create(struct lws *wsi)
|
|||
#else
|
||||
#if defined(LWS_USE_MBEDTLS)
|
||||
#else
|
||||
struct lws_context *context = wsi->context;
|
||||
char hostname[128], *p;
|
||||
|
||||
if (lws_hdr_copy(wsi, hostname, sizeof(hostname),
|
||||
|
@ -78,10 +135,11 @@ lws_ssl_client_bio_create(struct lws *wsi)
|
|||
X509_VERIFY_PARAM_set_hostflags(param,
|
||||
X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
|
||||
X509_VERIFY_PARAM_set1_host(param, hostname, 0);
|
||||
/* Configure a non-zero callback if desired */
|
||||
SSL_set_verify(wsi->ssl, SSL_VERIFY_PEER, 0);
|
||||
}
|
||||
|
||||
#endif
|
||||
/* OpenSSL_client_verify_callback will be called @ SSL_connect() */
|
||||
SSL_set_verify(wsi->ssl, SSL_VERIFY_PEER, OpenSSL_client_verify_callback);
|
||||
|
||||
#ifndef USE_WOLFSSL
|
||||
SSL_set_mode(wsi->ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
|
||||
|
@ -137,7 +195,7 @@ lws_ssl_client_bio_create(struct lws *wsi)
|
|||
#endif
|
||||
|
||||
SSL_set_ex_data(wsi->ssl, openssl_websocket_private_data_index,
|
||||
context);
|
||||
wsi);
|
||||
|
||||
return 0;
|
||||
#endif
|
||||
|
@ -325,6 +383,7 @@ lws_ssl_client_connect2(struct lws *wsi)
|
|||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* USE_WOLFSSL */
|
||||
#endif
|
||||
#endif
|
||||
|
|
Loading…
Add table
Reference in a new issue