diff --git a/READMEs/README.test-apps.md b/READMEs/README.test-apps.md index c488e747..1c872b2b 100644 --- a/READMEs/README.test-apps.md +++ b/READMEs/README.test-apps.md @@ -74,7 +74,7 @@ terminates. To stop the daemon, do ``` - $ kill cat /tmp/.lwsts-lock + $ kill \`cat /tmp/.lwsts-lock\` ``` If it finds a stale lock (the pid mentioned in the file does not exist any more) it will delete the lock and create a new one during startup. @@ -82,6 +82,60 @@ any more) it will delete the lock and create a new one during startup. If the lock is valid, the daemon will exit with a note on stderr that it was already running. +@section clicert Testing Client Certs + +Here is a very quick way to create a CA, and a client and server cert from it, +for testing. + +``` +$ cp -rp ./scripts/client-ca /tmp +$ cd /tmp/client-ca +$ ./create-ca.sh +$ ./create-server-cert.sh server +$ ./create-client-cert.sh client +``` + +The last step wants an export password, you will need this password again to +import the p12 format certificate into your browser. + +This will get you the following + +|name|function| +|----|--------| +|ca.pem|Your Certificate Authority cert| +|ca.key|Private key for the CA cert| +|client.pem|Client certificate, signed by your CA| +|client.key|Client private key| +|client.p12|combined client.pem + client.key in p12 format for browsers| +|server.pem|Server cert, signed by your CA| +|server.key|Server private key| + +You can confirm yourself the client and server certs are signed by the CA. + +``` + $ openssl verify -verbose -trusted ca.pem server.pem + $ openssl verify -verbose -trusted ca.pem client.pem +``` + +Import the client.p12 file into your browser. In FFOX57 it's + + - preferences + - Privacy & Security + - Certificates | View Certificates + - Certificate Manager | Your Certificates | Import... + - Enter the password you gave when creating client1.p12 + - Click OK. + +You can then run the test server like this: + +``` + $ libwebsockets-test-server -s -A ca.pem -K server.key -C server.pem -v +``` + +When you connect your browser to https://localhost:7681 after accepting the +selfsigned server cert, your browser will pop up a prompt to send the server +your client cert (the -v switch enables this). The server will only accept +a client cert that has been signed by ca.pem. @section sssl Using SSL on the server side diff --git a/scripts/client-ca/certindex.txt b/scripts/client-ca/certindex.txt new file mode 100644 index 00000000..e69de29b diff --git a/scripts/client-ca/create-ca.sh b/scripts/client-ca/create-ca.sh new file mode 100755 index 00000000..5c8e17a4 --- /dev/null +++ b/scripts/client-ca/create-ca.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +openssl genrsa -out ca.key 2048 && \ +printf "\\n\\n\\n\\n\\n\\n\\n" | \ +openssl req -config tmp.cnf -x509 -new -nodes -key ca.key -sha256 -days 1024 -out ca.pem + diff --git a/scripts/client-ca/create-client-cert.sh b/scripts/client-ca/create-client-cert.sh new file mode 100755 index 00000000..cee8cbd3 --- /dev/null +++ b/scripts/client-ca/create-client-cert.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +if [ -z "$1" ] ; then + echo "Usage $0 " + exit 1 +fi + +openssl genrsa -out $1.key 4096 && \ +printf "\\n\\n\\n\\n\\nlocalhost\\n\\n1234\\n\\n" | \ + openssl req -config tmp.cnf -new -key $1.key -out $1.csr && \ +openssl ca -config tmp.cnf \ + -keyfile ca.key \ + -cert ca.pem \ + -extensions usr_cert \ + -days 375 \ + -notext \ + -md sha256 \ + -in $1.csr \ + -out $1.pem && \ +openssl pkcs12 -export -in $1.pem -inkey $1.key -out $1.p12 + diff --git a/scripts/client-ca/create-server-cert.sh b/scripts/client-ca/create-server-cert.sh new file mode 100755 index 00000000..46a15900 --- /dev/null +++ b/scripts/client-ca/create-server-cert.sh @@ -0,0 +1,20 @@ +#!/bin/sh + +if [ -z "$1" ] ; then + echo "Usage $0 " + exit 1 +fi + +openssl genrsa -out $1.key 4096 && \ +printf "\\n\\n\\n\\n\\nlocalhost\\n\\n1234\\n\\n" | \ + openssl req -config tmp.cnf -new -key $1.key -out $1.csr && \ +openssl ca -config tmp.cnf \ + -keyfile ca.key \ + -cert ca.pem \ + -extensions server_cert \ + -days 375 \ + -notext \ + -md sha256 \ + -in $1.csr \ + -out $1.pem + diff --git a/scripts/client-ca/serial b/scripts/client-ca/serial new file mode 100644 index 00000000..8995c802 --- /dev/null +++ b/scripts/client-ca/serial @@ -0,0 +1 @@ +100003 diff --git a/scripts/client-ca/tmp.cnf b/scripts/client-ca/tmp.cnf new file mode 100644 index 00000000..af7f77b7 --- /dev/null +++ b/scripts/client-ca/tmp.cnf @@ -0,0 +1,74 @@ +# +# OpenSSL configuration file. +# + +# Establish working directory. + +dir = . + +[ ca ] +default_ca = CA_default + +[ CA_default ] +serial = $dir/serial +database = $dir/certindex.txt +new_certs_dir = $dir/certs +certificate = $dir/cacert.pem +private_key = $dir/private/cakey.pem +default_days = 365 +default_md = sha256 +preserve = no +email_in_dn = no +nameopt = default_ca +certopt = default_ca +policy = policy_match + +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional +[ usr_cert ] +[ server_cert ] +[ req ] +default_bits = 4096 # Size of keys +default_keyfile = key.pem # name of generated keys +default_md = sha256 # message digest algorithm +string_mask = nombstr # permitted characters +distinguished_name = req_distinguished_name +req_extensions = v3_req + +[ req_distinguished_name ] +# Variable name Prompt string +#------------------------- ---------------------------------- +0.organizationName = Organization Name (company) +organizationalUnitName = Organizational Unit Name (department, division) +emailAddress = Email Address +emailAddress_max = 40 +localityName = Locality Name (city, district) +stateOrProvinceName = State or Province Name (full name) +countryName = Country Name (2 letter code) +countryName_min = 2 +countryName_max = 2 +commonName = Common Name (hostname, IP, or your name) +commonName_max = 64 + +# Default values for the above, for consistency and less typing. +# Variable name Value +#------------------------ ------------------------------ +0.organizationName_default = libwebsockets-test +localityName_default = Xiaobitan +stateOrProvinceName_default = Taipei +countryName_default = TW +emailAddress = none@invalid + +[ v3_ca ] +basicConstraints = CA:TRUE +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer:always + +[ v3_req ] +basicConstraints = CA:FALSE +subjectKeyIdentifier = hash