]> prime8.dev >> repos - ttyd.git/commitdiff
Add support for the --check-origin option
authorShuanglei Tao <tsl0922@gmail.com>
Mon, 10 Oct 2016 15:33:00 +0000 (23:33 +0800)
committerShuanglei Tao <tsl0922@gmail.com>
Mon, 10 Oct 2016 15:42:11 +0000 (23:42 +0800)
requires libwebsockets 1.7.0+ since lws_parse_uri is available from 1.7.0

CMakeLists.txt
README.md
src/index.html
src/protocol.c
src/server.c
src/server.h

index c6fc9b2d01ceb7b7a6e8808ce83d436d6440ef37..161f2384602da79485f25214aed64abcdeeea3e5 100644 (file)
@@ -9,7 +9,7 @@ endif()
 
 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)
 
 find_package(OpenSSL REQUIRED)
index e44aa53736899bcf181153a1e7e43a04b6c82ed6..d4e131df64d1a110bfe79010766138569b479102 100644 (file)
--- a/README.md
+++ b/README.md
@@ -66,6 +66,7 @@ OPTIONS:
     --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)
     --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
     --ssl, -S               Enable ssl
     --ssl-cert, -C          Ssl certificate file path
index 25e5c63864e5d65f02a6fc60853b28d1a7862b54..6e1f6a968c916393fba3e2673e9adeb0a0d78cb4 100644 (file)
                         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) {
-                    data = event.data.slice(1);
+                    var data = event.data.slice(1);
                     switch(event.data[0]) {
                         case '0':
                             term.io.writeUTF8(window.atob(data));
                     var errorNode = document.createElement('div');
                     errorNode.style.cssText = [
                             "color: red",
+                            "background-color: white",
                             "font-size: x-large",
                             "opacity: 0.75",
                             "text-align: center",
                             "border: 0.1em dotted #ccc"
                     ].join(";");
                     errorNode.textContent = "Websocket handshake failed!";
-                    document.getElementById("terminal").appendChild(errorNode);
+                    document.getElementById('terminal').appendChild(errorNode);
                 };
             };
 
-
             var sendPing = function(ws) {
                 ws.send("1");
             };
index 5e68dcc517561e280ff724e9d08c8e7bfb41ed5f..d7b5c6fe1c760f7484a40296e144e0de15499755 100644 (file)
@@ -63,6 +63,29 @@ parse_window_size(const char *json) {
     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
 tty_client_destroy(struct tty_client *client) {
     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");
                 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;
         case LWS_CALLBACK_ESTABLISHED:
             client->exit = false;
index a401409fe5448204922147f6e44a3db1923f7706..0e4a96f2d59c1090e59faf36cc46172187275185 100644 (file)
@@ -34,13 +34,14 @@ static const struct option options[] = {
         {"ssl-key", required_argument, NULL, 'K'},
         {"ssl-ca", required_argument, NULL, 'A'},
         {"readonly", no_argument, NULL, 'R'},
+        {"check-origin", no_argument, NULL, 'O'},
         {"once", no_argument, NULL, 'o'},
         {"debug", required_argument, NULL, 'd'},
         {"version", no_argument, NULL, 'v'},
         {"help", no_argument, NULL, 'h'},
         {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() {
     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"
                     "    --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"
+                    "    --check-origin, -O      Do not allow websocket connection from different origin\n"
                     "    --once, -o              Accept only one client and exit on disconnection\n"
                     "    --ssl, -S               Enable ssl\n"
                     "    --ssl-cert, -C          Ssl certificate file path\n"
@@ -207,6 +209,9 @@ main(int argc, char **argv) {
             case 'R':
                 server->readonly = true;
                 break;
+            case 'O':
+                server->check_origin = true;
+                break;
             case 'o':
                 server->once = true;
                 break;
@@ -327,6 +332,8 @@ main(int argc, char **argv) {
     lwsl_notice("  start command: %s\n", server->command);
     lwsl_notice("  reconnect timeout: %ds\n", server->reconnect);
     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)
         lwsl_notice("  readonly: true\n");
     if (server->once)
index c985b07b5d7b9047860b321a59d4f66b37a372d0..2cd52f691a5267e35de9f898f439c0bd6a7b391e 100644 (file)
@@ -72,6 +72,7 @@ struct tty_server {
     int sig_code;                             // close signal
     char *sig_name;                           // human readable signal string
     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
     pthread_mutex_t lock;
 };