From 0177cdf2e3e8493a0336261664645d63d9fb2f77 Mon Sep 17 00:00:00 2001 From: Thibaut Ackermann Date: Mon, 15 May 2017 10:12:44 +0200 Subject: [PATCH 1/2] Move web-admin interface to dedicated (and configurable) ip:port --- src/apps/relay/mainrelay.c | 23 ++++ src/apps/relay/turn_admin_server.c | 177 +++++++++++++++++++++++++++++ src/apps/relay/turn_admin_server.h | 10 ++ src/server/ns_turn_server.c | 31 +---- 4 files changed, 211 insertions(+), 30 deletions(-) diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index 7aba10c..95e4bb8 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -606,6 +606,10 @@ static char Usage[] = "Usage: turnserver [options]\n" " For the security reasons, it is recommended to use the encrypted\n" " for of the password (see the -P command in the turnadmin utility).\n" " The dollar signs in the encrypted form must be escaped.\n" +" --no-web-admin Turn OFF the Web-admin support. By default it is always ON.\n" +" --web-admin-ip= Local system IP address to be used for Web-admin server endpoint. Default value\n" +" is 127.0.0.1.\n" +" --web-admin-port= Web-admin server port. Default is 8080.\n" " --server-relay Server relay. NON-STANDARD AND DANGEROUS OPTION. Only for those applications\n" " when we want to run server applications on the relay endpoints.\n" " This option eliminates the IP permissions check on the packets\n" @@ -725,6 +729,9 @@ enum EXTRA_OPTS { CLI_IP_OPT, CLI_PORT_OPT, CLI_PASSWORD_OPT, + NO_WEB_ADMIN_OPT, + WEB_ADMIN_IP_OPT, + WEB_ADMIN_PORT_OPT, SERVER_RELAY_OPT, CLI_MAX_SESSIONS_OPT, EC_CURVE_NAME_OPT, @@ -849,6 +856,9 @@ static const struct myoption long_options[] = { { "cli-ip", required_argument, NULL, CLI_IP_OPT }, { "cli-port", required_argument, NULL, CLI_PORT_OPT }, { "cli-password", required_argument, NULL, CLI_PASSWORD_OPT }, + { "no-web-admin", optional_argument, NULL, NO_WEB_ADMIN_OPT }, + { "web-admin-ip", required_argument, NULL, WEB_ADMIN_IP_OPT }, + { "web-admin-port", required_argument, NULL, WEB_ADMIN_PORT_OPT }, { "server-relay", optional_argument, NULL, SERVER_RELAY_OPT }, { "cli-max-output-sessions", required_argument, NULL, CLI_MAX_SESSIONS_OPT }, { "ec-curve-name", required_argument, NULL, EC_CURVE_NAME_OPT }, @@ -1005,6 +1015,19 @@ static void set_option(int c, char *value) case CLI_PASSWORD_OPT: STRCPY(cli_password,value); break; + case NO_WEB_ADMIN_OPT: + use_web_admin = !get_bool_value(value); + break; + case WEB_ADMIN_IP_OPT: + if(make_ioa_addr((const u08bits*)value, 0, &web_admin_addr) < 0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot set web-admin address: %s\n", value); + } else { + web_admin_addr_set = 1; + } + break; + case WEB_ADMIN_PORT_OPT: + web_admin_port = atoi(value); + break; case PROC_USER_OPT: { struct passwd* pwd = getpwnam(value); if(!pwd) { diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index 54c40a1..266a8b1 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -71,6 +71,8 @@ #include "dbdrivers/dbdriver.h" +#include "tls_listener.h" + /////////////////////////////// struct admin_server adminserver; @@ -86,6 +88,14 @@ char cli_password[CLI_PASSWORD_LENGTH] = ""; int cli_max_output_sessions = DEFAULT_CLI_MAX_OUTPUT_SESSIONS; + +int use_web_admin = 1; + +ioa_addr web_admin_addr; +int web_admin_addr_set = 0; + +int web_admin_port = WEB_ADMIN_DEFAULT_PORT; + /////////////////////////////// struct cli_session { @@ -1186,6 +1196,129 @@ static void cliserver_input_handler(struct evconnlistener *l, evutil_socket_t fd } } +static void web_admin_input_handler(ioa_socket_handle s, int event_type, + ioa_net_data *in_buffer, void *arg, int can_resume) { + + if (!arg) + return; + + UNUSED_ARG(event_type); + UNUSED_ARG(can_resume); + + ts_ur_super_session* ss = (ts_ur_super_session*)arg; + + if (ss->client_socket != s) { + return; + } + + int buffer_size = (int)ioa_network_buffer_get_size(in_buffer->nbh); + if (buffer_size > 0) { + + SOCKET_TYPE st = get_ioa_socket_type(ss->client_socket); + + if(is_stream_socket(st)) { + if(is_http((char*)ioa_network_buffer_data(in_buffer->nbh), buffer_size)) { + const char *proto = "HTTP"; + ioa_network_buffer_data(in_buffer->nbh)[buffer_size] = 0; + 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), (char*)ioa_network_buffer_data(in_buffer->nbh)); + + 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); + if(new_s) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s new detached socket: 0x%lx, st=%d, sat=%d\n", __FUNCTION__,(long)new_s, get_ioa_socket_type(new_s), get_ioa_socket_app_type(new_s)); + + send_https_socket(new_s); + } + ss->to_be_closed = 1; + + } else { + set_ioa_socket_app_type(ss->client_socket, HTTP_CLIENT_SOCKET); + if(adminserver.verbose) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: %s request: %s\n", __FUNCTION__, proto, (char*)ioa_network_buffer_data(in_buffer->nbh)); + } + handle_http_echo(ss->client_socket); + } + } + } + } + + if (ss->to_be_closed) { + if(adminserver.verbose) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, + "session %018llu: web-admin socket to be closed in client handler: ss=0x%lx\n", (unsigned long long)(ss->id), (long)ss); + } + set_ioa_socket_tobeclosed(s); + } +} + +static int send_socket_to_admin_server(ioa_engine_handle e, struct message_to_relay *sm) +{ + // sm->relay_server is null for us. + + sm->t = RMT_SOCKET; + + if (sm->m.sm.s->defer_nbh) { + if (!sm->m.sm.nd.nbh) { + sm->m.sm.nd.nbh = sm->m.sm.s->defer_nbh; + sm->m.sm.s->defer_nbh = NULL; + } else { + ioa_network_buffer_delete(e, sm->m.sm.s->defer_nbh); + sm->m.sm.s->defer_nbh = NULL; + } + } + + ioa_socket_handle s = sm->m.sm.s; + + if (!s) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: web-admin socket EMPTY\n", __FUNCTION__); + + } else if (s->read_event || s->bev) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, + "%s: web-admin socket wrongly preset: 0x%lx : 0x%lx\n", + __FUNCTION__, (long) s->read_event, (long) s->bev); + + IOA_CLOSE_SOCKET(s); + sm->m.sm.s = NULL; + } else { + s->e = e; + + struct socket_message *msg = &(sm->m.sm); + + ts_ur_super_session *ss = (ts_ur_super_session*)turn_malloc(sizeof(ts_ur_super_session)); + ns_bzero(ss, sizeof(ts_ur_super_session)); + + ss->client_socket = msg->s; + + if(register_callback_on_ioa_socket(e, ss->client_socket, IOA_EV_READ, + web_admin_input_handler, ss, 0) < 0) { + + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: Failed to register callback on web-admin ioa socket\n", __FUNCTION__); + IOA_CLOSE_SOCKET(s); + sm->m.sm.s = NULL; + + } else { + + set_ioa_socket_session(ss->client_socket, ss); + + if(msg->nd.nbh) { + web_admin_input_handler(ss->client_socket, IOA_EV_READ, &(msg->nd), ss, msg->can_resume); + ioa_network_buffer_delete(e, msg->nd.nbh); + msg->nd.nbh = NULL; + } + } + } + + ioa_network_buffer_delete(e, sm->m.sm.nd.nbh); + sm->m.sm.nd.nbh = NULL; + + return 0; +} + void setup_admin_thread(void) { adminserver.event_base = turn_event_base_new(); @@ -1197,6 +1330,25 @@ void setup_admin_thread(void) #endif ); + if(use_web_admin) { + // Support encryption on this ioa engine + // because the web-admin needs HTTPS + set_ssl_ctx(adminserver.e, turn_params.tls_ctx_ssl23, turn_params.tls_ctx_v1_0 +#if TLSv1_1_SUPPORTED + ,turn_params.tls_ctx_v1_1 +#if TLSv1_2_SUPPORTED + ,turn_params.tls_ctx_v1_2 +#endif +#endif +#if DTLS_SUPPORTED + ,turn_params.dtls_ctx +#endif +#if DTLSv1_2_SUPPORTED + ,turn_params.dtls_ctx_v1_2 +#endif + ); + } + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"IO method (admin thread): %s\n",event_base_get_method(adminserver.event_base)); { @@ -1223,6 +1375,31 @@ void setup_admin_thread(void) bufferevent_enable(adminserver.https_in_buf, EV_READ); } + + // Setup the web-admin server + if(use_web_admin) { + if(!web_admin_addr_set) { + if(make_ioa_addr((const u08bits*)WEB_ADMIN_DEFAULT_IP, 0, &web_admin_addr) < 0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot set web-admin address %s\n", WEB_ADMIN_DEFAULT_IP); + return; + } + } + + addr_set_port(&web_admin_addr, web_admin_port); + + char saddr[129]; + addr_to_string_no_port(&web_admin_addr,(u08bits*)saddr); + + tls_listener_relay_server_type *tls_service = create_tls_listener_server(turn_params.listener_ifname, saddr, web_admin_port, turn_params.verbose, adminserver.e, send_socket_to_admin_server, NULL); + + if (tls_service == NULL) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"Cannot create web-admin listener\n"); + return; + } + + addr_debug_print(adminserver.verbose, &web_admin_addr, "web-admin listener opened on "); + } + if(use_cli) { if(!cli_addr_set) { if(make_ioa_addr((const u08bits*)CLI_DEFAULT_IP,0,&cli_addr)<0) { diff --git a/src/apps/relay/turn_admin_server.h b/src/apps/relay/turn_admin_server.h index a1e5570..7edb47f 100644 --- a/src/apps/relay/turn_admin_server.h +++ b/src/apps/relay/turn_admin_server.h @@ -94,6 +94,16 @@ extern char cli_password[CLI_PASSWORD_LENGTH]; #define DEFAULT_CLI_MAX_OUTPUT_SESSIONS (256) extern int cli_max_output_sessions; + +extern int use_web_admin; + +#define WEB_ADMIN_DEFAULT_IP ("127.0.0.1") +extern ioa_addr web_admin_addr; +extern int web_admin_addr_set; + +#define WEB_ADMIN_DEFAULT_PORT (8080) +extern int web_admin_port; + //////////////////////////////////////////// void setup_admin_thread(void); diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 1045ba9..b6d0bc4 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -4542,37 +4542,8 @@ static int read_client_connection(turn_turnserver *server, return 0; } - } else { - SOCKET_TYPE st = get_ioa_socket_type(ss->client_socket); - if(is_stream_socket(st)) { - if(is_http((char*)ioa_network_buffer_data(in_buffer->nbh), ioa_network_buffer_get_size(in_buffer->nbh))) { - const char *proto = "HTTP"; - ioa_network_buffer_data(in_buffer->nbh)[ioa_network_buffer_get_size(in_buffer->nbh)] = 0; - 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), (char*)ioa_network_buffer_data(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); - if(new_s) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s new detached socket: 0x%lx, st=%d, sat=%d\n", __FUNCTION__,(long)new_s, get_ioa_socket_type(new_s), get_ioa_socket_app_type(new_s)); - server->send_https_socket(new_s); - } - ss->to_be_closed = 1; - } - } 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, (char*)ioa_network_buffer_data(in_buffer->nbh)); - } - handle_http_echo(ss->client_socket); - } - return 0; - } - } } - + //Unrecognized message received, ignore it FUNCEND; From 4988ef6ae80fe643ef0c924f75fa755e8469742c Mon Sep 17 00:00:00 2001 From: Thibaut Ackermann Date: Tue, 2 Oct 2018 15:51:01 +0200 Subject: [PATCH 2/2] fix memory leak in web_admin_input_handler --- src/apps/relay/turn_admin_server.c | 48 +++++++++++------------------- 1 file changed, 17 insertions(+), 31 deletions(-) diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index 266a8b1..71de2b6 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -1198,23 +1198,16 @@ static void cliserver_input_handler(struct evconnlistener *l, evutil_socket_t fd static void web_admin_input_handler(ioa_socket_handle s, int event_type, ioa_net_data *in_buffer, void *arg, int can_resume) { - - if (!arg) - return; - UNUSED_ARG(event_type); UNUSED_ARG(can_resume); - - ts_ur_super_session* ss = (ts_ur_super_session*)arg; - - if (ss->client_socket != s) { - return; - } - + UNUSED_ARG(arg); + + int to_be_closed = 0; + int buffer_size = (int)ioa_network_buffer_get_size(in_buffer->nbh); if (buffer_size > 0) { - SOCKET_TYPE st = get_ioa_socket_type(ss->client_socket); + SOCKET_TYPE st = get_ioa_socket_type(s); if(is_stream_socket(st)) { if(is_http((char*)ioa_network_buffer_data(in_buffer->nbh), buffer_size)) { @@ -1222,35 +1215,35 @@ static void web_admin_input_handler(ioa_socket_handle s, int event_type, ioa_network_buffer_data(in_buffer->nbh)[buffer_size] = 0; if(st == TLS_SOCKET) { proto = "HTTPS"; - set_ioa_socket_app_type(ss->client_socket, HTTPS_CLIENT_SOCKET); + set_ioa_socket_app_type(s, 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), (char*)ioa_network_buffer_data(in_buffer->nbh)); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: %s (%s %s) request: %s\n", __FUNCTION__, proto, get_ioa_socket_cipher(s), get_ioa_socket_ssl_method(s), (char*)ioa_network_buffer_data(in_buffer->nbh)); - 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)s, get_ioa_socket_type(s), get_ioa_socket_app_type(s)); - ioa_socket_handle new_s = detach_ioa_socket(ss->client_socket); + ioa_socket_handle new_s = detach_ioa_socket(s); if(new_s) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s new detached socket: 0x%lx, st=%d, sat=%d\n", __FUNCTION__,(long)new_s, get_ioa_socket_type(new_s), get_ioa_socket_app_type(new_s)); send_https_socket(new_s); } - ss->to_be_closed = 1; + to_be_closed = 1; } else { - set_ioa_socket_app_type(ss->client_socket, HTTP_CLIENT_SOCKET); + set_ioa_socket_app_type(s, HTTP_CLIENT_SOCKET); if(adminserver.verbose) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: %s request: %s\n", __FUNCTION__, proto, (char*)ioa_network_buffer_data(in_buffer->nbh)); } - handle_http_echo(ss->client_socket); + handle_http_echo(s); } } } } - if (ss->to_be_closed) { + if (to_be_closed) { if(adminserver.verbose) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, - "session %018llu: web-admin socket to be closed in client handler: ss=0x%lx\n", (unsigned long long)(ss->id), (long)ss); + "%s: web-admin socket to be closed in client handler: s=0x%lx\n", __FUNCTION__, (long)s); } set_ioa_socket_tobeclosed(s); } @@ -1289,13 +1282,8 @@ static int send_socket_to_admin_server(ioa_engine_handle e, struct message_to_re struct socket_message *msg = &(sm->m.sm); - ts_ur_super_session *ss = (ts_ur_super_session*)turn_malloc(sizeof(ts_ur_super_session)); - ns_bzero(ss, sizeof(ts_ur_super_session)); - - ss->client_socket = msg->s; - - if(register_callback_on_ioa_socket(e, ss->client_socket, IOA_EV_READ, - web_admin_input_handler, ss, 0) < 0) { + if(register_callback_on_ioa_socket(e, msg->s, IOA_EV_READ, + web_admin_input_handler, NULL, 0) < 0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: Failed to register callback on web-admin ioa socket\n", __FUNCTION__); IOA_CLOSE_SOCKET(s); @@ -1303,10 +1291,8 @@ static int send_socket_to_admin_server(ioa_engine_handle e, struct message_to_re } else { - set_ioa_socket_session(ss->client_socket, ss); - if(msg->nd.nbh) { - web_admin_input_handler(ss->client_socket, IOA_EV_READ, &(msg->nd), ss, msg->can_resume); + web_admin_input_handler(msg->s, IOA_EV_READ, &(msg->nd), NULL, msg->can_resume); ioa_network_buffer_delete(e, msg->nd.nbh); msg->nd.nbh = NULL; }