mirror of
https://github.com/tsl0922/ttyd.git
synced 2025-12-23 04:14:18 +01:00
Add support for the --check-origin option
requires libwebsockets 1.7.0+ since lws_parse_uri is available from 1.7.0
This commit is contained in:
@@ -9,7 +9,7 @@ endif()
|
|||||||
|
|
||||||
project(ttyd)
|
project(ttyd)
|
||||||
|
|
||||||
set(LIBWEBSOCKETS_MIN_VERSION 1.6)
|
set(LIBWEBSOCKETS_MIN_VERSION 1.7.0)
|
||||||
set(SOURCE_FILES src/server.c src/http.c src/protocol.c src/utils.c)
|
set(SOURCE_FILES src/server.c src/http.c src/protocol.c src/utils.c)
|
||||||
|
|
||||||
find_package(OpenSSL REQUIRED)
|
find_package(OpenSSL REQUIRED)
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ OPTIONS:
|
|||||||
--signal, -s Signal to send to the command when exit it (default: SIGHUP)
|
--signal, -s Signal to send to the command when exit it (default: SIGHUP)
|
||||||
--reconnect, -r Time to reconnect for the client in seconds (default: 10)
|
--reconnect, -r Time to reconnect for the client in seconds (default: 10)
|
||||||
--readonly, -R Do not allow clients to write to the TTY
|
--readonly, -R Do not allow clients to write to the TTY
|
||||||
|
--check-origin, -O Do not allow websocket connection from different origin
|
||||||
--once, -o Accept only one client and exit on disconnection
|
--once, -o Accept only one client and exit on disconnection
|
||||||
--ssl, -S Enable ssl
|
--ssl, -S Enable ssl
|
||||||
--ssl-cert, -C Ssl certificate file path
|
--ssl-cert, -C Ssl certificate file path
|
||||||
|
|||||||
12
src/index.html
vendored
12
src/index.html
vendored
@@ -616,11 +616,15 @@
|
|||||||
term.installKeyboard();
|
term.installKeyboard();
|
||||||
};
|
};
|
||||||
|
|
||||||
term.decorate(document.getElementById("terminal"));
|
var termContainer = document.getElementById('terminal');
|
||||||
|
while (termContainer.firstChild) {
|
||||||
|
termContainer.removeChild(termContainer.firstChild);
|
||||||
|
}
|
||||||
|
term.decorate(termContainer);
|
||||||
};
|
};
|
||||||
|
|
||||||
ws.onmessage = function(event) {
|
ws.onmessage = function(event) {
|
||||||
data = event.data.slice(1);
|
var data = event.data.slice(1);
|
||||||
switch(event.data[0]) {
|
switch(event.data[0]) {
|
||||||
case '0':
|
case '0':
|
||||||
term.io.writeUTF8(window.atob(data));
|
term.io.writeUTF8(window.atob(data));
|
||||||
@@ -662,6 +666,7 @@
|
|||||||
var errorNode = document.createElement('div');
|
var errorNode = document.createElement('div');
|
||||||
errorNode.style.cssText = [
|
errorNode.style.cssText = [
|
||||||
"color: red",
|
"color: red",
|
||||||
|
"background-color: white",
|
||||||
"font-size: x-large",
|
"font-size: x-large",
|
||||||
"opacity: 0.75",
|
"opacity: 0.75",
|
||||||
"text-align: center",
|
"text-align: center",
|
||||||
@@ -670,11 +675,10 @@
|
|||||||
"border: 0.1em dotted #ccc"
|
"border: 0.1em dotted #ccc"
|
||||||
].join(";");
|
].join(";");
|
||||||
errorNode.textContent = "Websocket handshake failed!";
|
errorNode.textContent = "Websocket handshake failed!";
|
||||||
document.getElementById("terminal").appendChild(errorNode);
|
document.getElementById('terminal').appendChild(errorNode);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
var sendPing = function(ws) {
|
var sendPing = function(ws) {
|
||||||
ws.send("1");
|
ws.send("1");
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -63,6 +63,29 @@ parse_window_size(const char *json) {
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
check_host_origin(struct lws *wsi) {
|
||||||
|
int origin_length = lws_hdr_total_length(wsi, WSI_TOKEN_ORIGIN);
|
||||||
|
char buf[origin_length + 1];
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
int len = lws_hdr_copy(wsi, buf, sizeof(buf), WSI_TOKEN_ORIGIN);
|
||||||
|
if (len > 0) {
|
||||||
|
const char *prot, *address, *path;
|
||||||
|
int port;
|
||||||
|
if (lws_parse_uri(buf, &prot, &address, &port, &path))
|
||||||
|
return false;
|
||||||
|
sprintf(buf, "%s:%d", address, port);
|
||||||
|
int host_length = lws_hdr_total_length(wsi, WSI_TOKEN_HOST);
|
||||||
|
if (host_length != strlen(buf))
|
||||||
|
return false;
|
||||||
|
char host_buf[host_length + 1];
|
||||||
|
memset(host_buf, 0, sizeof(host_buf));
|
||||||
|
len = lws_hdr_copy(wsi, host_buf, sizeof(host_buf), WSI_TOKEN_HOST);
|
||||||
|
return len > 0 && strcasecmp(buf, host_buf) == 0;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
tty_client_destroy(struct tty_client *client) {
|
tty_client_destroy(struct tty_client *client) {
|
||||||
if (client->exit || client->pid <= 0)
|
if (client->exit || client->pid <= 0)
|
||||||
@@ -164,6 +187,10 @@ callback_tty(struct lws *wsi, enum lws_callback_reasons reason,
|
|||||||
lwsl_notice("refuse to serve new client due to the --once option.\n");
|
lwsl_notice("refuse to serve new client due to the --once option.\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if (server->check_origin && !check_host_origin(wsi)) {
|
||||||
|
lwsl_notice("refuse to serve new client from different origin due to the --check-origin option.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case LWS_CALLBACK_ESTABLISHED:
|
case LWS_CALLBACK_ESTABLISHED:
|
||||||
client->exit = false;
|
client->exit = false;
|
||||||
|
|||||||
@@ -34,13 +34,14 @@ static const struct option options[] = {
|
|||||||
{"ssl-key", required_argument, NULL, 'K'},
|
{"ssl-key", required_argument, NULL, 'K'},
|
||||||
{"ssl-ca", required_argument, NULL, 'A'},
|
{"ssl-ca", required_argument, NULL, 'A'},
|
||||||
{"readonly", no_argument, NULL, 'R'},
|
{"readonly", no_argument, NULL, 'R'},
|
||||||
|
{"check-origin", no_argument, NULL, 'O'},
|
||||||
{"once", no_argument, NULL, 'o'},
|
{"once", no_argument, NULL, 'o'},
|
||||||
{"debug", required_argument, NULL, 'd'},
|
{"debug", required_argument, NULL, 'd'},
|
||||||
{"version", no_argument, NULL, 'v'},
|
{"version", no_argument, NULL, 'v'},
|
||||||
{"help", no_argument, NULL, 'h'},
|
{"help", no_argument, NULL, 'h'},
|
||||||
{NULL, 0, 0, 0}
|
{NULL, 0, 0, 0}
|
||||||
};
|
};
|
||||||
static const char *opt_string = "p:i:c:u:g:s:r:aSC:K:A:Rod:vh";
|
static const char *opt_string = "p:i:c:u:g:s:r:aSC:K:A:ROod:vh";
|
||||||
|
|
||||||
void print_help() {
|
void print_help() {
|
||||||
fprintf(stderr, "ttyd is a tool for sharing terminal over the web\n\n"
|
fprintf(stderr, "ttyd is a tool for sharing terminal over the web\n\n"
|
||||||
@@ -57,6 +58,7 @@ void print_help() {
|
|||||||
" --signal, -s Signal to send to the command when exit it (default: SIGHUP)\n"
|
" --signal, -s Signal to send to the command when exit it (default: SIGHUP)\n"
|
||||||
" --reconnect, -r Time to reconnect for the client in seconds (default: 10)\n"
|
" --reconnect, -r Time to reconnect for the client in seconds (default: 10)\n"
|
||||||
" --readonly, -R Do not allow clients to write to the TTY\n"
|
" --readonly, -R Do not allow clients to write to the TTY\n"
|
||||||
|
" --check-origin, -O Do not allow websocket connection from different origin\n"
|
||||||
" --once, -o Accept only one client and exit on disconnection\n"
|
" --once, -o Accept only one client and exit on disconnection\n"
|
||||||
" --ssl, -S Enable ssl\n"
|
" --ssl, -S Enable ssl\n"
|
||||||
" --ssl-cert, -C Ssl certificate file path\n"
|
" --ssl-cert, -C Ssl certificate file path\n"
|
||||||
@@ -207,6 +209,9 @@ main(int argc, char **argv) {
|
|||||||
case 'R':
|
case 'R':
|
||||||
server->readonly = true;
|
server->readonly = true;
|
||||||
break;
|
break;
|
||||||
|
case 'O':
|
||||||
|
server->check_origin = true;
|
||||||
|
break;
|
||||||
case 'o':
|
case 'o':
|
||||||
server->once = true;
|
server->once = true;
|
||||||
break;
|
break;
|
||||||
@@ -327,6 +332,8 @@ main(int argc, char **argv) {
|
|||||||
lwsl_notice(" start command: %s\n", server->command);
|
lwsl_notice(" start command: %s\n", server->command);
|
||||||
lwsl_notice(" reconnect timeout: %ds\n", server->reconnect);
|
lwsl_notice(" reconnect timeout: %ds\n", server->reconnect);
|
||||||
lwsl_notice(" close signal: %s (%d)\n", server->sig_name, server->sig_code);
|
lwsl_notice(" close signal: %s (%d)\n", server->sig_name, server->sig_code);
|
||||||
|
if (server->check_origin)
|
||||||
|
lwsl_notice(" check origin: true\n");
|
||||||
if (server->readonly)
|
if (server->readonly)
|
||||||
lwsl_notice(" readonly: true\n");
|
lwsl_notice(" readonly: true\n");
|
||||||
if (server->once)
|
if (server->once)
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ struct tty_server {
|
|||||||
int sig_code; // close signal
|
int sig_code; // close signal
|
||||||
char *sig_name; // human readable signal string
|
char *sig_name; // human readable signal string
|
||||||
bool readonly; // whether not allow clients to write to the TTY
|
bool readonly; // whether not allow clients to write to the TTY
|
||||||
|
bool check_origin; // whether allow websocket connection from different origin
|
||||||
bool once; // whether accept only one client and exit on disconnection
|
bool once; // whether accept only one client and exit on disconnection
|
||||||
pthread_mutex_t lock;
|
pthread_mutex_t lock;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user