浏览代码

fix acme wrt. security, redundancy, consistency

Jens Elkner 4 年之前
父节点
当前提交
8c99505614
共有 3 个文件被更改,包括 37 次插入57 次删除
  1. 11 0
      configure
  2. 26 55
      src/apps/relay/acme.c
  3. 0 2
      src/apps/relay/acme.h

+ 11 - 0
configure

@@ -556,6 +556,17 @@ if [ "${SYSTEM}" = "NetBSD" ] ; then
 	fi
 fi
 
+# If acme_redirect does not work, send_data_from_ioa_socket_nbh() probably
+# does not work. Set LIBEV_OK=1 to use a workaround for it.
+if [ -z "${LIBEV_OK}" ]; then
+	LIBEV_OK=1
+	if [ "${SYSTEM}" = "Linux" ]; then
+		OS=$( lsb_release -si 2>/dev/null )
+		[ "${OS}" = "Ubuntu" ] || LIBEV_OK=0
+	fi
+fi
+[ "${LIBEV_OK}" = "1" ] && OSCFLAGS="${OSCFLAGS} -DLIBEV_OK"
+
 ###########################
 # Install shell commands
 ###########################

+ 26 - 55
src/apps/relay/acme.c

@@ -1,43 +1,22 @@
 
 /*
- * Copyright (C) 2011, 2012, 2013, 2014 Citrix Systems
+ * Copyright (C) 2020 Jens Elkner.  All rights reserved.
  *
- * 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.
+ * License: MIT - see https://opensource.org/licenses/MIT
  */
 
 #include "acme.h"
 #include "ns_ioalib_impl.h"
 
+#define GET_ACME_PREFIX "GET /.well-known/acme-challenge/"
+#define GET_ACME_PREFIX_LEN 32
+
 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))
+	if (strncmp(req, GET_ACME_PREFIX, GET_ACME_PREFIX_LEN))
 		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
@@ -45,15 +24,15 @@ static int is_acme_req(char *req, size_t len) {
 	len =- 21;					// min size of trailing headers
 	if (len > 131)
 		len = 131;
-	for (i=32; i < (int) len; i++) {
+	for (i=GET_ACME_PREFIX_LEN; 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))
+		if (i < (GET_ACME_PREFIX_LEN + 10) || strncmp(req + i, " HTTP/1.", 8))
 			return -2;
 		// finally check for allowed chars
-		for (k=32; k < i; k++) {
+		for (k=GET_ACME_PREFIX_LEN; k < i; k++) {
 			c = req[k];
 			if ((c > 127) || (A[c] == ' '))
 				return -3;
@@ -71,51 +50,43 @@ int try_acme_redirect(char *req, size_t len, const char *url,
 		"<html><head><title>301 Moved Permanently</title></head>\
 		<body><h1>301 Moved Permanently</h1></body></html>";
 	char http_response[1024];
-	char req_url[600];
-	char *req_url_end_space, *req_url_end_tab;
-	int path_length;
-	strcpy(req_url, req + GET_WELLKNOWN_ACMECHALLANGE_URL_PREFIX_LENGTH);
-	req_url_end_space=strchr(req_url,' ');
-	req_url_end_tab=strchr(req_url,'\t');
-	if (req_url_end_space != NULL && req_url_end_tab != NULL) {
-		if (req_url_end_space - req_url_end_tab > 0 ){
-			path_length=req_url_end_space - req_url;
-			req_url[path_length]='\0';
-		} else {
-			path_length=req_url_end_tab - req_url;
-			req_url[req_url_end_tab - req_url]='\0';
-		}
-	} else if(req_url_end_space != NULL) {
-		path_length=req_url_end_space - req_url;
-		req_url[path_length]='\0';
-	}
-	else if(req_url_end_tab != NULL) {
-		path_length=req_url_end_tab - req_url;
-		req_url[path_length]='\0';
-	}
-
 	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)
+	if (len < (GET_ACME_PREFIX_LEN + 32) || len > (512 - GET_ACME_PREFIX_LEN)
+			|| (plen = is_acme_req(req, len)) < (GET_ACME_PREFIX_LEN + 1))
 		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_url, HTML);
+		"\r\n%s", strlen(HTML), url, req + GET_ACME_PREFIX_LEN, HTML);
 
 	rlen = strlen(http_response);
 
+#ifdef LIBEV_OK
 	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);
+#else
+	if (write(s->fd, http_response, rlen) == -1) {
+		TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING,
+			"Sending redirect to '%s%s' failed",url, req + GET_ACME_PREFIX_LEN);
+	} else if (((turn_turnserver *)s->session->server)->verbose) {
+		TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "ACME redirected to %s%s\n",
+			url, req + GET_ACME_PREFIX_LEN);
+	}
+#endif
+
+	req[plen] = ' ';
 
 	return 0;
 }

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

@@ -44,8 +44,6 @@ extern "C" {
 
 ///////////// ACME /////////////////////
 
-#define GET_WELLKNOWN_ACMECHALLANGE_URL_PREFIX_LENGTH 32
-
 int try_acme_redirect(char *req, size_t len, const char *url, ioa_socket_handle s);
 
 ///////////////////////////////////////