1
0
Fork 0
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:
Andy Green 2017-11-02 06:22:44 +08:00
parent 0c254aba87
commit a5514d2b2b
7 changed files with 130 additions and 18 deletions

View file

@ -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 ---^ ******/
};

View file

@ -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);

View file

@ -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;

View file

@ -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);

View file

@ -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) {

View file

@ -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);

View file

@ -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)
{