Browse Source

Move acme to new file

Mészáros Mihály 5 năm trước cách đây
mục cha
commit
d4686750ee

+ 3 - 1
ChangeLog

@@ -1,7 +1,7 @@
 24/06/2020 Oleg Moskalenko <[email protected]> Mihály Mészáros <[email protected]>
 Version 4.5.2 'dan Eider':
 	- fix null pointer dereference in case of out of memory. (thanks to Thomas Moeller for the report)
-    - merge PR #517 (by wolmi)
+	- merge PR #517 (by wolmi)
 		* add prometheus metrics
 	- merge PR #637 (by David Florness)
 	    * Delete trailing whitespace in example configuration files
@@ -21,6 +21,8 @@ Version 4.5.2 'dan Eider':
 	- update Docker mongoDB and fix with workaround the missing systemctl
 	- merge PR #660 (by Camden Narzt)
 		* fix compilation on macOS Big Sur
+	- merge PR #546 (by jelmd)
+		* Add ACME redirect url
 
 24/06/2020 Oleg Moskalenko <[email protected]> Mihály Mészáros <[email protected]>
 Version 4.5.1.3 'dan Eider':

+ 1 - 1
Makefile.in

@@ -21,7 +21,7 @@ COMMON_MODS = src/apps/common/apputils.c src/apps/common/ns_turn_utils.c src/app
 COMMON_DEPS = ${LIBCLIENTTURN_DEPS} ${COMMON_MODS} ${COMMON_HEADERS}
 
 IMPL_HEADERS = src/apps/relay/ns_ioalib_impl.h src/apps/relay/ns_sm.h src/apps/relay/turn_ports.h
-IMPL_MODS = src/apps/relay/ns_ioalib_engine_impl.c src/apps/relay/turn_ports.c src/apps/relay/http_server.c
+IMPL_MODS = src/apps/relay/ns_ioalib_engine_impl.c src/apps/relay/turn_ports.c src/apps/relay/http_server.c src/apps/relay/acme.c
 IMPL_DEPS = ${COMMON_DEPS} ${IMPL_HEADERS} ${IMPL_MODS}
 
 HIREDIS_HEADERS = src/apps/common/hiredis_libevent2.h

+ 0 - 7
man/man1/turnserver.1

@@ -787,13 +787,6 @@ File name to store the pid of the process.
 Default is /var/run/turnserver.pid (if superuser account is used) or
 /var/tmp/turnserver.pid .
 .TP
-.BI --acme-redirect\  URL
-Redirect ACME/RFC8555 (like Let's Encrypt challenge) requests, i.e.
-HTTP GET requests matching '^/.well-known/acme-challenge/(.*)'
-to \fIURL\fR$1 with $1 == (.*).  No validation of \fIURL\fR will be done,
-so make sure you do not forget the trailing slash. If \fIURL\fR is an empty
-string (the default value), no special handling of such requests will be done.
-.TP
 .B
 \fB\-\-proc\-user\fP
 User name to run the process. After the initialization, the \fIturnserver\fP process

+ 111 - 0
src/apps/relay/acme.c

@@ -0,0 +1,111 @@
+
+/*
+ * Copyright (C) 2011, 2012, 2013, 2014 Citrix Systems
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "acme.h"
+#include "ns_ioalib_impl.h"
+
+static int is_acme_req(char *req, size_t len) {
+	static const char *A = "                                             -  0123456789       ABCDEFGHIJKLMNOPQRSTUVWXYZ    _ abcdefghijklmnopqrstuvwxyz     ";
+	int c, i, k;
+
+	// Check first request line. Should be like: GET path HTTP/1.x
+	if (strncmp(req, "GET /.well-known/acme-challenge/", 32))
+		return -1;
+	// Usually (for LE) the "method path" is 32 + 43 = 55 chars. But other
+	// implementations may choose longer pathes. We define PATHMAX = 127 chars
+	// to be prepared for "DoS" attacks (STUN msg size max. is ~ 64K).
+	len =- 21;					// min size of trailing headers
+	if (len > 131)
+		len = 131;
+	for (i=32; i < (int) len; i++) {
+		// find the end of the path
+		if (req[i] != ' ')
+			continue;
+		// consider path < 10 chars invalid. Also we wanna see a "trailer".
+		if (i < 42 || strncmp(req + i, " HTTP/1.", 8))
+			return -2;
+		// finally check for allowed chars
+		for (k=32; k < i; k++) {
+			c = req[k];
+			if ((c > 127) || (A[c] == ' '))
+				return -3;
+		}
+		// all checks passed: sufficient for us to answer with a redirect
+		return i;
+	}
+	return -4;		// end of path not found
+}
+
+int try_acme_redirect(char *req, size_t len, const char *url,
+	ioa_socket_handle s)
+{
+	static const char *HTML = "<html><head><title>301 Moved Permanently</title></head><body><h1>301 Moved Permanently</h1></body></html>";
+	char http_response[1024];
+	size_t plen, rlen;
+
+	if (url == NULL || url[0] == '\0' || req == NULL || s == 0 )
+		return 1;
+	if (len < 64 || len > 512 || (plen = is_acme_req(req, len)) < 33)
+		return 2;
+
+	
+	snprintf(http_response, sizeof(http_response) - 1,
+		"HTTP/1.1 301 Moved Permanently\r\n"
+		"Content-Type: text/html\r\n"
+		"Content-Length: %ld\r\n"
+		"Connection: close\r\n"
+		"Location: %s%s\r\n"
+		"\r\n%s", strlen(HTML), url, req + 32, HTML);
+
+	rlen = strlen(http_response);
+
+	// Variant A: direkt write, no eventbuf stuff
+	/*
+	if (write(s->fd, http_response, rlen) == -1) {
+		perror("Sending redirect failed");
+	} else if (((turn_turnserver *)s->session->server)->verbose) {
+		TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "ACME redirect to %s%s\n",
+			url, req + 32);
+	}
+
+	req[plen] = ' ';
+     */
+	// Variant B: via eventbuf does not send anything for whatever reason
+	
+	//set_ioa_socket_app_type(s, HTTP_CLIENT_SOCKET);
+	ioa_network_buffer_handle nbh_acme = ioa_network_buffer_allocate(s->e);
+	uint8_t *data = ioa_network_buffer_data(nbh_acme);
+	bcopy(http_response, data, rlen);
+	ioa_network_buffer_set_size(nbh_acme, rlen);
+	send_data_from_ioa_socket_nbh(s, NULL, nbh_acme, TTL_IGNORE, TOS_IGNORE, NULL);
+
+	return 0;
+}

+ 57 - 0
src/apps/relay/acme.h

@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2011, 2012, 2013, 2014 Citrix Systems
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef __TURN_ACME__
+#define __TURN_ACME__
+
+#include "ns_turn_utils.h"
+#include "ns_turn_server.h"
+#include "apputils.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////// ACME /////////////////////
+
+int try_acme_redirect(char *req, size_t len, const char *url, ioa_socket_handle s);
+
+///////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/// __TURN_ACME__ ///
+

+ 0 - 77
src/apps/relay/http_server.c

@@ -99,83 +99,6 @@ const char* get_http_date_header()
 	return buffer_header;
 }
 
-static int is_acme_req(char *req, size_t len) {
-	static const char *A = "                                             -  0123456789       ABCDEFGHIJKLMNOPQRSTUVWXYZ    _ abcdefghijklmnopqrstuvwxyz     ";
-	int c, i, k;
-
-	// Check first request line. Should be like: GET path HTTP/1.x
-	if (strncmp(req, "GET /.well-known/acme-challenge/", 32))
-		return -1;
-	// Usually (for LE) the "method path" is 32 + 43 = 55 chars. But other
-	// implementations may choose longer pathes. We define PATHMAX = 127 chars
-	// to be prepared for "DoS" attacks (STUN msg size max. is ~ 64K).
-	len =- 21;					// min size of trailing headers
-	if (len > 131)
-		len = 131;
-	for (i=32; i < (int) len; i++) {
-		// find the end of the path
-		if (req[i] != ' ')
-			continue;
-		// consider path < 10 chars invalid. Also we wanna see a "trailer".
-		if (i < 42 || strncmp(req + i, " HTTP/1.", 8))
-			return -2;
-		// finally check for allowed chars
-		for (k=32; k < i; k++) {
-			c = req[k];
-			if ((c > 127) || (A[c] == ' '))
-				return -3;
-		}
-		// all checks passed: sufficient for us to answer with a redirect
-		return i;
-	}
-	return -4;		// end of path not found
-}
-
-int try_acme_redirect(char *req, size_t len, const char *url,
-	ioa_socket_handle s)
-{
-	static const char *HTML = "<html><head><title>301 Moved Permanently</title></head><body><h1>301 Moved Permanently</h1></body></html>";
-	char http_response[1024];
-	int plen, rlen;
-
-	if (url == NULL || url[0] == '\0' || req == NULL || s == 0 )
-		return 1;
-	if (len < 64 || len > 512 || (plen = is_acme_req(req, len)) < 33)
-		return 2;
-
-	req[plen] = '\0';
-	snprintf(http_response, sizeof(http_response) - 1,
-		"HTTP/1.1 301 Moved Permanently\r\n"
-		"Content-Type: text/html\r\n"
-		"Content-Length: %ld\r\n"
-		"Connection: close\r\n"
-		"Location: %s%s\r\n"
-		"\r\n%s", strlen(HTML), url, req + 32, HTML);
-
-	rlen = strlen(http_response);
-
-	// Variant A: direkt write, no eventbuf stuff
-	if (write(s->fd, http_response, rlen) == -1) {
-		perror("Sending redirect failed");
-	} else if (((turn_turnserver *)s->session->server)->verbose) {
-		TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "ACME redirect to %s%s\n",
-			url, req + 32);
-	}
-
-	req[plen] = ' ';
-
-	// Variant B: via eventbuf does not send anything for whatever reason
-	/*
-	set_ioa_socket_app_type(s, HTTP_CLIENT_SOCKET);
-	ioa_network_buffer_handle nbh = ioa_network_buffer_allocate(s->e);
-	uint8_t *data = ioa_network_buffer_data(nbh);
-	bcopy(http_response, data, rlen);
-	ioa_network_buffer_set_size(nbh, rlen);
-	send_data_from_ioa_socket_nbh(s, NULL, nbh, TTL_IGNORE, TOS_IGNORE, NULL);
-	*/
-
-	return 0;
-}
 ///////////////////////////////////////////////
 
 static struct headers_list * post_parse(char *data, size_t data_len)

+ 3 - 0
src/server/ns_turn_ioalib.h

@@ -285,6 +285,9 @@ int get_default_protocol_port(const char* scheme, size_t slen);
 ///////////// HTTP ////////////////////
 
 void handle_http_echo(ioa_socket_handle s);
+
+///////////// ACME /////////////////////
+
 int try_acme_redirect(char *req, size_t len, const char *url, ioa_socket_handle s);
 
 ///////////////////////////////////////

+ 12 - 7
src/server/ns_turn_server.c

@@ -4624,19 +4624,24 @@ static int read_client_connection(turn_turnserver *server,
 	} else {
 		SOCKET_TYPE st = get_ioa_socket_type(ss->client_socket);
 		if(is_stream_socket(st)) {
-			char *str = (char*)ioa_network_buffer_data(in_buffer->nbh);
-			size_t l = ioa_network_buffer_get_size(in_buffer->nbh);
-			if(is_http(str, l)) {
+			if(is_http((char*)ioa_network_buffer_data(in_buffer->nbh), 
+			ioa_network_buffer_get_size(in_buffer->nbh))) {
+
 				const char *proto = "HTTP";
-				str[l] = 0;
-				if ((st == TCP_SOCKET) && (try_acme_redirect(str, l, server->acme_redirect, ss->client_socket) == 0)) {
+				if ((st == TCP_SOCKET) && 
+					(
+						try_acme_redirect((char*)ioa_network_buffer_data(in_buffer->nbh),
+						ioa_network_buffer_get_size(in_buffer->nbh),
+						server->acme_redirect, ss->client_socket) == 0
+					)
+				) {
 					ss->to_be_closed = 1;
 					return 0;
 				} else if (*server->web_admin_listen_on_workers) {
 					if(st==TLS_SOCKET) {
 						proto = "HTTPS";
 						set_ioa_socket_app_type(ss->client_socket,HTTPS_CLIENT_SOCKET);
-						TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: %s (%s %s) request: %s\n", __FUNCTION__, proto, get_ioa_socket_cipher(ss->client_socket), get_ioa_socket_ssl_method(ss->client_socket), str);
+						TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: %s (%s %s) request: %s\n", __FUNCTION__, proto, get_ioa_socket_cipher(ss->client_socket), get_ioa_socket_ssl_method(ss->client_socket), ioa_network_buffer_get_size(in_buffer->nbh));
 						if(server->send_https_socket) {
 							TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s socket to be detached: 0x%lx, st=%d, sat=%d\n", __FUNCTION__,(long)ss->client_socket, get_ioa_socket_type(ss->client_socket), get_ioa_socket_app_type(ss->client_socket));
 							ioa_socket_handle new_s = detach_ioa_socket(ss->client_socket);
@@ -4649,7 +4654,7 @@ static int read_client_connection(turn_turnserver *server,
 					} else {
 						set_ioa_socket_app_type(ss->client_socket,HTTP_CLIENT_SOCKET);
 						if(server->verbose) {
-							TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: %s request: %s\n", __FUNCTION__, proto, str);
+							TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: %s request: %s\n", __FUNCTION__, proto, ioa_network_buffer_get_size(in_buffer->nbh));
 						}
 						handle_http_echo(ss->client_socket);
 					}