]> prime8.dev >> repos - ttyd.git/commitdiff
Enable client certificate verification if ssl CA is given
authorShuanglei Tao <tsl0922@gmail.com>
Wed, 23 Nov 2016 15:19:32 +0000 (23:19 +0800)
committerShuanglei Tao <tsl0922@gmail.com>
Wed, 23 Nov 2016 15:34:56 +0000 (23:34 +0800)
README.md
src/http.c
src/protocol.c
src/server.c

index 01878eacd07f7697b06d92fb208b846397045265..58548d9d7988ea9a7e9961144a6e4823242a8795 100644 (file)
--- a/README.md
+++ b/README.md
@@ -70,10 +70,10 @@ OPTIONS:
     --client-option, -t     Send option to client (format: key=value), repeat to add more options
     --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
-    --ssl-key, -K           Ssl key file path
-    --ssl-ca, -A            Ssl ca file path
+    --ssl, -S               Enable SSL
+    --ssl-cert, -C          SSL certificate file path
+    --ssl-key, -K           SSL key file path
+    --ssl-ca, -A            SSL CA file path for client certificate verification
     --debug, -d             Set log level (0-9, default: 7)
     --version, -v           Print the version and exit
     --help, -h              Print this text and exit
@@ -94,6 +94,32 @@ Then open <http://localhost:8080> with a broswer, you will get a bash shell with
 - You can even run a none shell command like vim, try: `ttyd vim`, the web broswer will show you a vim editor.
 - Sharing single process with multiple clients: `ttyd tmux new -A -s ttyd vim`, run `tmux new -A -s ttyd` to connect to the tmux session from terminal.
 
+## SSL how-to
+
+Generate SSL CA and self signed server/client certificates:
+
+```bash
+# CA
+openssl genrsa -out ca.key 4096
+openssl req -new -x509 -days 365 -key ca.key -out ca.crt
+# server certificate
+openssl req -newkey rsa:2048 -nodes -keyout server.key -out server.csr
+openssl x509 -req -days 365 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt
+# client certificate (the p12/pem format may be useful for some clients)
+openssl req -newkey rsa:2048 -nodes -keyout client.key -out client.csr
+openssl x509 -req -days 365 -in client.csr -CA ca.crt -CAkey ca.key -set_serial 02 -out client.crt
+openssl pkcs12 -export -clcerts -in client.crt -inkey client.key -out client.p12
+openssl pkcs12 -in client.p12 -out client.pem -clcerts
+```
+
+Then start ttyd:
+
+```bash
+ttyd --ssl --ssl-cert ca.crt --ssl-key ca.key --ssl-ca ca.crt bash
+```
+
+If you don't want to enable client certificate verification, remove the `--ssl-ca` option.
+
 ## Docker and ttyd
 
 Docker containers are jailed environments which are more secure, this is useful for protecting the host system, you may use ttyd with docker like this:
index 52e207fdfc532c5232e953c21ce5ad63cca99b7f..25026514d35957197f46a367b7d6f71d0b9019ba 100644 (file)
@@ -127,6 +127,15 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, voi
             if (lws_write_http(wsi, index_html, index_html_len) < 0)
                 return 1;
             goto try_to_reuse;
+        case LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION:
+            if (!len || (SSL_get_verify_result((SSL*)in) != X509_V_OK)) {
+                int err = X509_STORE_CTX_get_error((X509_STORE_CTX*)user);
+                int depth = X509_STORE_CTX_get_error_depth((X509_STORE_CTX*)user);
+                const char* msg = X509_verify_cert_error_string(err);
+                lwsl_err("client certificate verification error: %s (%d), depth: %d\n", msg, err, depth);
+                return 1;
+            }
+            break;
         default:
             break;
     }
index 776aba17c7e306a5ec99a55c37d1cdebb9763ca7..d3ef9254709685ad7e128cecc326ff00d8fefb9f 100644 (file)
@@ -133,7 +133,7 @@ thread_run_command(void *args) {
     pid_t pid = forkpty(&pty, NULL, NULL, NULL);
 
     switch (pid) {
-        case -1: /* */
+        case -1: /* error */
             lwsl_err("forkpty\n");
             break;
         case 0: /* child */
index 44edae5be937ff0f5bc0bb712a3bdc7810a20dea..d40baa4d4839eaa4eceb7999fe72b75821625b89 100644 (file)
@@ -61,10 +61,10 @@ void print_help() {
                     "    --client-option, -t     Send option to client (format: key=value), repeat to add more options\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"
-                    "    --ssl-key, -K           Ssl key file path\n"
-                    "    --ssl-ca, -A            Ssl ca file path\n"
+                    "    --ssl, -S               Enable SSL\n"
+                    "    --ssl-cert, -C          SSL certificate file path\n"
+                    "    --ssl-key, -K           SSL key file path\n"
+                    "    --ssl-ca, -A            SSL CA file path for client certificate verification\n"
                     "    --debug, -d             Set log level (0-9, default: 7)\n"
                     "    --version, -v           Print the version and exit\n"
                     "    --help, -h              Print this text and exit\n",
@@ -332,6 +332,8 @@ main(int argc, char **argv) {
                 "!DHE-RSA-AES256-SHA256:"
                 "!AES256-GCM-SHA384:"
                 "!AES256-SHA256";
+        if (strlen(info.ssl_ca_filepath) > 0)
+            info.options |= LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT;
 #if LWS_LIBRARY_VERSION_MAJOR == 2
         info.options |= LWS_SERVER_OPTION_REDIRECT_HTTP_TO_HTTPS;
 #endif