diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index 84dea49..71fb915 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -625,6 +625,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" @@ -749,6 +753,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, @@ -875,6 +882,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 }, @@ -1176,6 +1186,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/mainrelay.h b/src/apps/relay/mainrelay.h index 02249ec..88e7322 100644 --- a/src/apps/relay/mainrelay.h +++ b/src/apps/relay/mainrelay.h @@ -349,6 +349,9 @@ void del_tls_alternate_server(const char *saddr); void add_listener_addr(const char* addr); int add_relay_addr(const char* addr); +////////// SSL CTX //////////////////// +void set_ssl_ctx(ioa_engine_handle e, turn_params_t *params); + ///////// Auth //////////////// void send_auth_message_to_auth_server(struct auth_message *am); diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c index 88a3838..797c092 100644 --- a/src/apps/relay/netengine.c +++ b/src/apps/relay/netengine.c @@ -334,7 +334,7 @@ static void update_ssl_ctx(evutil_socket_t sock, short events, update_ssl_ctx_cb UNUSED_ARG(events); } -static void set_ssl_ctx(ioa_engine_handle e, turn_params_t *params) +void set_ssl_ctx(ioa_engine_handle e, turn_params_t *params) { update_ssl_ctx_cb_args_t *args = (update_ssl_ctx_cb_args_t *)turn_malloc(sizeof(update_ssl_ctx_cb_args_t)); args->engine = e; diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index 6b6806b..961ea36 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,12 @@ 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); + } + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"IO method (admin thread): %s\n",event_base_get_method(adminserver.event_base)); { @@ -1223,6 +1362,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 f983796..f6d84fd 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -4573,37 +4573,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;