mirror of
https://github.com/warmcat/libwebsockets.git
synced 2025-03-09 00:00:04 +01:00
LWS_SERVER_OPTION_IGNORE_MISSING_CERT
This commit is contained in:
parent
0c254aba87
commit
a5514d2b2b
7 changed files with 130 additions and 18 deletions
|
@ -2515,6 +2515,12 @@ enum lws_context_options {
|
|||
* call LWS_CALLBACK_PROTOCOL_INIT on its protocols. It's used in the
|
||||
* special case of a temporary vhost bound to a single protocol.
|
||||
*/
|
||||
LWS_SERVER_OPTION_IGNORE_MISSING_CERT = (1 << 26),
|
||||
/**< (VH) Don't fail if the vhost TLS cert or key are missing, just
|
||||
* continue. The vhost won't be able to serve anything, but if for
|
||||
* example the ACME plugin was configured to fetch a cert, this lets
|
||||
* you bootstrap your vhost from having no cert to start with.
|
||||
*/
|
||||
|
||||
/****** add new things just above ---^ ******/
|
||||
};
|
||||
|
|
|
@ -1042,6 +1042,7 @@ struct lws_vhost {
|
|||
|
||||
unsigned int created_vhost_protocols:1;
|
||||
unsigned int being_destroyed:1;
|
||||
unsigned int skipped_certs:1;
|
||||
|
||||
unsigned char default_protocol_index;
|
||||
unsigned char raw_protocol_index;
|
||||
|
@ -2377,6 +2378,14 @@ LWS_EXTERN void lwsl_emit_stderr(int level, const char *line);
|
|||
#define lws_tls_acme_sni_cert_destroy(_a)
|
||||
#else
|
||||
#define LWS_SSL_ENABLED(context) (context->use_ssl)
|
||||
|
||||
enum lws_tls_extant {
|
||||
LWS_TLS_EXTANT_NO,
|
||||
LWS_TLS_EXTANT_YES,
|
||||
LWS_TLS_EXTANT_ALTERNATIVE
|
||||
};
|
||||
LWS_EXTERN enum lws_tls_extant
|
||||
lws_tls_use_any_upgrade_check_extant(const char *name);
|
||||
LWS_EXTERN int openssl_websocket_private_data_index;
|
||||
LWS_EXTERN int LWS_WARN_UNUSED_RESULT
|
||||
lws_ssl_capable_read(struct lws *wsi, unsigned char *buf, int len);
|
||||
|
|
|
@ -100,6 +100,7 @@ static const char * const paths_vhosts[] = {
|
|||
"vhosts[].client-ssl-ciphers",
|
||||
"vhosts[].onlyraw",
|
||||
"vhosts[].client-cert-required",
|
||||
"vhosts[].ignore-missing-cert",
|
||||
};
|
||||
|
||||
enum lejp_vhost_paths {
|
||||
|
@ -148,6 +149,7 @@ enum lejp_vhost_paths {
|
|||
LEJPVP_CLIENT_CIPHERS,
|
||||
LEJPVP_FLAG_ONLYRAW,
|
||||
LEJPVP_FLAG_CLIENT_CERT_REQUIRED,
|
||||
LEJPVP_IGNORE_MISSING_CERT,
|
||||
};
|
||||
|
||||
static const char * const parser_errs[] = {
|
||||
|
@ -690,6 +692,14 @@ lejp_vhosts_cb(struct lejp_ctx *ctx, char reason)
|
|||
LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT;
|
||||
return 0;
|
||||
|
||||
case LEJPVP_IGNORE_MISSING_CERT:
|
||||
if (arg_to_bool(ctx->buf))
|
||||
a->info->options |= LWS_SERVER_OPTION_IGNORE_MISSING_CERT;
|
||||
else
|
||||
a->info->options &= ~(LWS_SERVER_OPTION_IGNORE_MISSING_CERT);
|
||||
|
||||
return 0;
|
||||
|
||||
case LEJPVP_SSL_OPTION_SET:
|
||||
a->info->ssl_options_set |= atol(ctx->buf);
|
||||
return 0;
|
||||
|
|
|
@ -255,12 +255,13 @@ lws_tls_server_vhost_backend_init(struct lws_context_creation_info *info,
|
|||
* parameter.
|
||||
*/
|
||||
n = lws_tls_use_any_upgrade_check_extant(info->ssl_cert_filepath);
|
||||
if (n < 0)
|
||||
if (n == LWS_TLS_EXTANT_ALTERNATIVE)
|
||||
return 1;
|
||||
m = lws_tls_use_any_upgrade_check_extant(info->ssl_private_key_filepath);
|
||||
if (m < 0)
|
||||
if (m == LWS_TLS_EXTANT_ALTERNATIVE)
|
||||
return 1;
|
||||
if ((n || m) && (info->options & LWS_SERVER_OPTION_IGNORE_MISSING_CERT)) {
|
||||
if ((n == LWS_TLS_EXTANT_NO || m == LWS_TLS_EXTANT_NO) &&
|
||||
(info->options & LWS_SERVER_OPTION_IGNORE_MISSING_CERT)) {
|
||||
lwsl_notice("Ignoring missing %s or %s\n",
|
||||
info->ssl_cert_filepath,
|
||||
info->ssl_private_key_filepath);
|
||||
|
|
|
@ -347,7 +347,11 @@ lws_tls_client_create_vhost_context(struct lws_vhost *vh,
|
|||
|
||||
/* support for client-side certificate authentication */
|
||||
if (cert_filepath) {
|
||||
lwsl_notice("%s: doing cert filepath\n", __func__);
|
||||
if (lws_tls_use_any_upgrade_check_extant(cert_filepath) != LWS_TLS_EXTANT_YES &&
|
||||
(info->options & LWS_SERVER_OPTION_IGNORE_MISSING_CERT))
|
||||
return 0;
|
||||
|
||||
lwsl_notice("%s: doing cert filepath %s\n", __func__, cert_filepath);
|
||||
n = SSL_CTX_use_certificate_chain_file(vh->ssl_client_ctx,
|
||||
cert_filepath);
|
||||
if (n < 1) {
|
||||
|
|
|
@ -224,12 +224,13 @@ lws_tls_server_vhost_backend_init(struct lws_context_creation_info *info,
|
|||
*/
|
||||
|
||||
n = lws_tls_use_any_upgrade_check_extant(info->ssl_cert_filepath);
|
||||
if (n < 0)
|
||||
if (n == LWS_TLS_EXTANT_ALTERNATIVE)
|
||||
return 1;
|
||||
m = lws_tls_use_any_upgrade_check_extant(info->ssl_private_key_filepath);
|
||||
if (m < 0)
|
||||
if (m == LWS_TLS_EXTANT_ALTERNATIVE)
|
||||
return 1;
|
||||
if ((n || m) && (info->options & LWS_SERVER_OPTION_IGNORE_MISSING_CERT)) {
|
||||
if ((n == LWS_TLS_EXTANT_NO || m == LWS_TLS_EXTANT_NO) &&
|
||||
(info->options & LWS_SERVER_OPTION_IGNORE_MISSING_CERT)) {
|
||||
lwsl_notice("Ignoring missing %s or %s\n",
|
||||
info->ssl_cert_filepath,
|
||||
info->ssl_private_key_filepath);
|
||||
|
|
103
lib/tls/tls.c
103
lib/tls/tls.c
|
@ -102,22 +102,23 @@ int
|
|||
lws_tls_check_cert_lifetime(struct lws_vhost *v)
|
||||
{
|
||||
union lws_tls_cert_info_results ir;
|
||||
time_t now = (time_t)lws_now_secs(), life;
|
||||
time_t now = (time_t)lws_now_secs(), life = 0;
|
||||
int n;
|
||||
|
||||
if (!v->ssl_ctx)
|
||||
return -1;
|
||||
if (v->ssl_ctx && !v->skipped_certs) {
|
||||
|
||||
if (now < 1464083026) /* May 2016 */
|
||||
/* our clock is wrong and we can't judge the certs */
|
||||
return -1;
|
||||
if (now < 1464083026) /* May 2016 */
|
||||
/* our clock is wrong and we can't judge the certs */
|
||||
return -1;
|
||||
|
||||
n = lws_tls_vhost_cert_info(v, LWS_TLS_CERT_INFO_VALIDITY_TO, &ir, 0);
|
||||
if (n)
|
||||
return -1;
|
||||
n = lws_tls_vhost_cert_info(v, LWS_TLS_CERT_INFO_VALIDITY_TO, &ir, 0);
|
||||
if (n)
|
||||
return -1;
|
||||
|
||||
life = (ir.time - now) / (24 * 3600);
|
||||
lwsl_notice(" vhost %s: cert expiry: %dd\n", v->name, (int)life);
|
||||
life = (ir.time - now) / (24 * 3600);
|
||||
lwsl_notice(" vhost %s: cert expiry: %dd\n", v->name, (int)life);
|
||||
} else
|
||||
lwsl_notice(" vhost %s: no cert\n", v->name);
|
||||
|
||||
lws_broadcast(v->context, LWS_CALLBACK_VHOST_CERT_AGING, v,
|
||||
(size_t)(ssize_t)life);
|
||||
|
@ -138,6 +139,86 @@ lws_tls_check_all_cert_lifetimes(struct lws_context *context)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
lws_tls_extant(const char *name)
|
||||
{
|
||||
/* it exists if we can open it... */
|
||||
int fd = open(name, O_RDONLY), n;
|
||||
char buf[1];
|
||||
|
||||
if (fd < 0)
|
||||
return 1;
|
||||
|
||||
/* and we can read at least one byte out of it */
|
||||
n = read(fd, buf, 1);
|
||||
close(fd);
|
||||
|
||||
return n != 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns 0 if the filepath "name" exists and can be read from.
|
||||
*
|
||||
* In addition, if "name".upd exists, backup "name" to "name.old.1"
|
||||
* and rename "name".upd to "name" before reporting its existence.
|
||||
*
|
||||
* There are four situations and three results possible:
|
||||
*
|
||||
* 1) LWS_TLS_EXTANT_NO: There are no certs at all (we are waiting for them to
|
||||
* be provisioned)
|
||||
*
|
||||
* 2) There are provisioned certs written (xxx.upd) and we still have root
|
||||
* privs... in this case we rename any existing cert to have a backup name
|
||||
* and move the upd cert into place with the correct name. This then becomes
|
||||
* situation 4 for the caller.
|
||||
*
|
||||
* 3) LWS_TLS_EXTANT_ALTERNATIVE: There are provisioned certs written (xxx.upd)
|
||||
* but we no longer have the privs needed to read or rename them. In this
|
||||
* case, indicate that the caller should use temp copies if any we do have
|
||||
* rights to access. This is normal after we have updated the cert.
|
||||
*
|
||||
* 4) LWS_TLS_EXTANT_YES: The certs are present with the correct name and we
|
||||
* have the rights to read them.
|
||||
*/
|
||||
|
||||
enum lws_tls_extant
|
||||
lws_tls_use_any_upgrade_check_extant(const char *name)
|
||||
{
|
||||
char buf[256];
|
||||
int n;
|
||||
|
||||
lws_snprintf(buf, sizeof(buf) - 1, "%s.upd", name);
|
||||
if (!lws_tls_extant(buf)) {
|
||||
/* ah there is an updated file... how about the desired file? */
|
||||
if (!lws_tls_extant(name)) {
|
||||
/* rename the desired file */
|
||||
for (n = 0; n < 50; n++) {
|
||||
lws_snprintf(buf, sizeof(buf) - 1,
|
||||
"%s.old.%d", name, n);
|
||||
if (!rename(name, buf))
|
||||
break;
|
||||
}
|
||||
if (n == 50) {
|
||||
lwsl_notice("unable to rename %s\n", name);
|
||||
|
||||
return LWS_TLS_EXTANT_ALTERNATIVE;
|
||||
}
|
||||
lws_snprintf(buf, sizeof(buf) - 1, "%s.upd", name);
|
||||
}
|
||||
/* desired file is out of the way, rename the updated file */
|
||||
if (rename(buf, name)) {
|
||||
lwsl_notice("unable to rename %s to %s\n", buf, name);
|
||||
|
||||
return LWS_TLS_EXTANT_ALTERNATIVE;
|
||||
}
|
||||
}
|
||||
|
||||
if (lws_tls_extant(name))
|
||||
return LWS_TLS_EXTANT_NO;
|
||||
|
||||
return LWS_TLS_EXTANT_YES;
|
||||
}
|
||||
|
||||
int
|
||||
lws_gate_accepts(struct lws_context *context, int on)
|
||||
{
|
||||
|
|
Loading…
Add table
Reference in a new issue