1
0
mirror of https://github.com/coturn/coturn.git synced 2025-10-25 21:11:00 +02:00

fix acme wrt. security, redundancy, consistency

This commit is contained in:
Jens Elkner 2020-12-31 16:39:00 +01:00
parent 8dc5bbcb3b
commit 8c99505614
3 changed files with 37 additions and 57 deletions

11
configure vendored
View File

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

View File

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

View File

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