Browse Source

Merge pull request #284 from gaida/master

Improved certificate hot swap for use with short lived certificates
bel2125 9 năm trước cách đây
mục cha
commit
1d0faa4220
2 tập tin đã thay đổi với 59 bổ sung12 xóa
  1. 12 0
      docs/UserManual.md
  2. 47 12
      src/civetweb.c

+ 12 - 0
docs/UserManual.md

@@ -439,6 +439,18 @@ TLS1.0+TLS1.1+TLS1.2 | 2
 TLS1.1+TLS1.2 | 3
 TLS1.2 | 4
 
+### ssl_short_trust `no`
+Enables the use of short lived certificates. This will allow for the certificates
+and keys specified in `ssl_certificate`, `ssl_ca_file` and `ssl_ca_path` to be 
+exchanged and reloaded while the server is running.
+
+In an automated environment it is advised to first write the new pem file to
+a different filename and then to rename it to the configured pem file name to
+increase performance while swapping the certificate.
+
+Disk IO performance can be improved when keeping the certificates and keys stored
+on a tmpfs (linux) on a system with very high throughput.
+
 # Lua Scripts and Lua Server Pages
 Pre-built Windows and Mac civetweb binaries have built-in Lua scripting
 support as well as support for Lua Server Pages.

+ 47 - 12
src/civetweb.c

@@ -10584,20 +10584,30 @@ ssl_id_callback(void)
 #endif
 }
 
-static pthread_mutex_t *ssl_mutexes;
 static int ssl_use_pem_file(struct mg_context *ctx, const char *pem);
 static const char * ssl_error(void);
 
 static int
-sslize(struct mg_connection *conn, SSL_CTX *s, int (*func)(SSL *))
+refresh_trust(struct mg_connection *conn)
 {
-	int ret, err;
-	if (!conn) {
+	static int reload_lock = 0;
+	static long int data_check = 0;
+
+	char *pem;
+	if ((pem = conn->ctx->config[SSL_CERTIFICATE]) == NULL
+		&& conn->ctx->callbacks.init_ssl == NULL) {
 		return 0;
 	}
 
-	int short_trust = !strcmp(conn->ctx->config[SSL_SHORT_TRUST], "yes");
-	if (short_trust) {
+	struct stat cert_buf;
+	long int t = data_check;
+	if (stat(pem, &cert_buf) != -1) {
+		t = (long int) cert_buf.st_mtime;
+	}
+
+	if (data_check != t) {
+		data_check = t;
+
 		int should_verify_peer =
 				(conn->ctx->config[SSL_DO_VERIFY_PEER] != NULL)
 				&& (mg_strcasecmp(conn->ctx->config[SSL_DO_VERIFY_PEER], "yes") == 0);
@@ -10618,15 +10628,40 @@ sslize(struct mg_connection *conn, SSL_CTX *s, int (*func)(SSL *))
 			}
 		}
 
-		char *pem;
-		if ((pem = conn->ctx->config[SSL_CERTIFICATE]) == NULL
-			&& conn->ctx->callbacks.init_ssl == NULL) {
-			return 0;
+		if (!reload_lock) {
+			reload_lock = 1;
+			if (ssl_use_pem_file(conn->ctx, pem) == 0) {
+				return 0;
+			}
+			reload_lock = 0;
 		}
-		if (ssl_use_pem_file(conn->ctx, pem) == 0) {
-			return 0;
+	}
+	/* lock while cert is reloading */
+	while (reload_lock) {
+		sleep(1);
+	}
+
+	return 1;
+}
+
+static pthread_mutex_t *ssl_mutexes;
+
+static int
+sslize(struct mg_connection *conn, SSL_CTX *s, int (*func)(SSL *))
+{
+	int ret, err;
+	if (!conn) {
+		return 0;
+	}
+
+	int short_trust = !strcmp(conn->ctx->config[SSL_SHORT_TRUST], "yes");
+	if (short_trust) {
+		int trust_ret = refresh_trust(conn);
+		if (!trust_ret) {
+			return trust_ret;
 		}
 	}
+
 	conn->ssl = SSL_new(s);
 	if (conn->ssl == NULL) {
 		return 0;