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

Move acme to new file

This commit is contained in:
Mészáros Mihály 2020-08-08 22:47:41 +02:00
parent 9b0dd4380c
commit d4686750ee
8 changed files with 187 additions and 93 deletions

View File

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

View File

@ -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} 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_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} IMPL_DEPS = ${COMMON_DEPS} ${IMPL_HEADERS} ${IMPL_MODS}
HIREDIS_HEADERS = src/apps/common/hiredis_libevent2.h HIREDIS_HEADERS = src/apps/common/hiredis_libevent2.h

View File

@ -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 Default is /var/run/turnserver.pid (if superuser account is used) or
/var/tmp/turnserver.pid . /var/tmp/turnserver.pid .
.TP .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 .B
\fB\-\-proc\-user\fP \fB\-\-proc\-user\fP
User name to run the process. After the initialization, the \fIturnserver\fP process User name to run the process. After the initialization, the \fIturnserver\fP process

111
src/apps/relay/acme.c Normal file
View File

@ -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
src/apps/relay/acme.h Normal file
View File

@ -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__ ///

View File

@ -99,83 +99,6 @@ const char* get_http_date_header()
return buffer_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) static struct headers_list * post_parse(char *data, size_t data_len)

View File

@ -285,6 +285,9 @@ int get_default_protocol_port(const char* scheme, size_t slen);
///////////// HTTP //////////////////// ///////////// HTTP ////////////////////
void handle_http_echo(ioa_socket_handle s); 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); int try_acme_redirect(char *req, size_t len, const char *url, ioa_socket_handle s);
/////////////////////////////////////// ///////////////////////////////////////

View File

@ -4624,19 +4624,24 @@ static int read_client_connection(turn_turnserver *server,
} else { } else {
SOCKET_TYPE st = get_ioa_socket_type(ss->client_socket); SOCKET_TYPE st = get_ioa_socket_type(ss->client_socket);
if(is_stream_socket(st)) { if(is_stream_socket(st)) {
char *str = (char*)ioa_network_buffer_data(in_buffer->nbh); if(is_http((char*)ioa_network_buffer_data(in_buffer->nbh),
size_t l = ioa_network_buffer_get_size(in_buffer->nbh); ioa_network_buffer_get_size(in_buffer->nbh))) {
if(is_http(str, l)) {
const char *proto = "HTTP"; const char *proto = "HTTP";
str[l] = 0; if ((st == TCP_SOCKET) &&
if ((st == TCP_SOCKET) && (try_acme_redirect(str, l, server->acme_redirect, ss->client_socket) == 0)) { (
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; ss->to_be_closed = 1;
return 0; return 0;
} else if (*server->web_admin_listen_on_workers) { } else if (*server->web_admin_listen_on_workers) {
if(st==TLS_SOCKET) { if(st==TLS_SOCKET) {
proto = "HTTPS"; proto = "HTTPS";
set_ioa_socket_app_type(ss->client_socket,HTTPS_CLIENT_SOCKET); 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) { 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)); 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); ioa_socket_handle new_s = detach_ioa_socket(ss->client_socket);
@ -4649,7 +4654,7 @@ static int read_client_connection(turn_turnserver *server,
} else { } else {
set_ioa_socket_app_type(ss->client_socket,HTTP_CLIENT_SOCKET); set_ioa_socket_app_type(ss->client_socket,HTTP_CLIENT_SOCKET);
if(server->verbose) { 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); handle_http_echo(ss->client_socket);
} }