cl-async

SSL over TCP

Cl-async provides a way to wrap your sockets in SSL.

Note that SSL in cl-async must be specifically loaded via the package cl-async-ssl, otherwise it won’t be available.

ssl-socket

extends socket

This class is much like the socket class, except that it houses a socket that has been wrapped in an SSL filter. It exposes no public accessors, except for the ones it inherits from socket.

It can be passed to any cl-async function that takes a socket argument.

tcp-ssl-connect

(defun tcp-ssl-connect (host port read-cb event-cb
                        &key data stream
                             connect-cb write-cb
                             (read-timeout -1) (write-timeout -1)
                             (dont-drain-read-buffer nil dont-drain-read-buffer-supplied-p)
                             ssl-ctx ssl-options ciphers)
  => ssl-socket/stream

Much like tcp-connect, tcp-connect-ssl opens and connects an async socket, but wrapped in the SSL protocol. In fact just about every argument is the same for tcp-connect as it is for tcp-connect-ssl, except for some special options that tcp-connect-ssl takes to help set up the SSL context/object.

tcp-ssl-connect returns an ssl-socket object, which is an extension of the socket class, and can be used with all the same functions/methods.

:ssl-ctx is an (optional) c-pointer to an SSL context object that you have initialized outside of cl-async. If a context is not specified, one is created and attached to the resulting socket.

:ssl-options is a list of options that allows us to set options on the created CTX. Note that if :ssl-ctx is supplied, :ssl-options is ignored. Options can be as follows:

+ssl-op-no-query-mtu+
+ssl-op-cookie-exchange+
+ssl-op-no-ticket+
+ssl-op-cisco-anyconnect+
+ssl-op-no-session-resumption-on-renegotiation+
+ssl-op-no-compression+
+ssl-op-allow-unsafe-legacy-renegotiation+
+ssl-op-single-ecdh-use+
+ssl-op-single-dh-use+
+ssl-op-ephemeral-rsa+
+ssl-op-cipher-server-preference+
+ssl-op-tls-rollback-bug+
+ssl-op-no-sslv2+
+ssl-op-no-sslv3+
+ssl-op-no-tlsv1+
+ssl-op-no-tlsv1-2+
+ssl-op-no-tlsv1-1+

:ciphers is a string cipher list you want the SSL object to be initialized with. The default is "HIGH:!RC4:!MD5:!aNULL:!EDH:!EXP:+ECDHE-RSA-AES128-SHA256:+3DES". Note that if :ssl-ctx is supplied, :ciphers is ignored.

;; simple SSL socket example
(tcp-ssl-connect "www.google.com" 443
                 (lambda (socket data)
                   (declare (ignore socket))
                   (format t "GOT: ~a~%" (babel:octets-to-string data)))
                 (lambda (ev)
                   (format t "EV: ~a~%" ev))
                 :read-timeout 3
                 :data (format nil "GET /~c~c" #\return #\newline))

read-cb definition (default)
(lambda (socket byte-array) ...)

read-cb definition (when tcp-ssl-connect’s :stream is t)
(lambda (socket stream) ...)

Note that in this case, stream replaces the data byte array’s position. Also, when calling :stream t in tcp-ssl-connect, the read buffer for the socket is not drained and is only done so by reading from the stream.

stream is always the same object returned from tcp-ssl-connect with :stream t. It wraps the ssl-socket object.

connect-cb definition
(lambda (socket) ...)

The connect-cb will be fired when the connection from tcp-ssl-connect has been established. Since sending data over the socket is somewhat transparent (either via :data or write-socket-data), you don’t really have to know when a socket is ready to be written to. In some instances though, it may be useful to know when the connection has been established, which is why :connect-cb is exposed.

write-cb definition
(lambda (socket) ...)

The write-cb will be called after data written to the socket’s buffer is flushed out to the socket. If you want to send a command to a server and immediately disconnect once you know the data was sent, you could close the connection in your write-cb.

tcp-ssl-server (class)

extends tcp-server

This is an opaque class which is returned by the function tcp-ssl-server to allow closing the server and allowing for future expansion of the server’s abilities. It has no public accessors.

tcp-ssl-server

(defun tcp-ssl-server (bind-address port read-cb event-cb
                       &key connect-cb (backlog -1) stream
                            ssl-ctx
                            certificate key (keytype :pem) ssl-options ciphers)
  => tcp-ssl-server

This function works by calling tcp-server to bind to the given address/port. It then replaces the callback that is fired when a new connection is accepted with one that wraps the incoming socket in the SSL protocol. In other words, tcp-ssl-server functions almost exactly like tcp-server except the connecting client must speak SSL.

It takes :certificate, :key, :keytype keyword arguments which are used for loading a certificate and a private key. The certificate file can be a chain file, so if you have a Certificate Authority you want to use, you can just dump it in the same file (much like how NginX handles SSL).

Like tcp-server, tcp-ssl-server can be closed gracefully by calling the close-tcp-server method on the tcp-ssl-server object it returns.

:ssl-ctx is an (optional) c-pointer to an SSL context object that you have initialized outside of cl-async. If a context is not specified, one is created and attached to the resulting server.

:ssl-options is a list of options that allows us to set options on the created CTX. Note that if :ssl-ctx is supplied, :ssl-options is ignored. Options can be as follows:

+ssl-op-no-query-mtu+
+ssl-op-cookie-exchange+
+ssl-op-no-ticket+
+ssl-op-cisco-anyconnect+
+ssl-op-no-session-resumption-on-renegotiation+
+ssl-op-no-compression+
+ssl-op-allow-unsafe-legacy-renegotiation+
+ssl-op-single-ecdh-use+
+ssl-op-single-dh-use+
+ssl-op-ephemeral-rsa+
+ssl-op-cipher-server-preference+
+ssl-op-tls-rollback-bug+
+ssl-op-no-sslv2+
+ssl-op-no-sslv3+
+ssl-op-no-tlsv1+
+ssl-op-no-tlsv1-2+
+ssl-op-no-tlsv1-1+

:ciphers is a string cipher list you want the SSL object to be initialized with. The default is "HIGH:!RC4:!MD5:!aNULL:!EDH:!EXP:+ECDHE-RSA-AES128-SHA256:+3DES". Note that if :ssl-ctx is supplied, :ciphers is ignored.

;; example
(tcp-ssl-server "127.0.0.1" 443
                (lambda (socket data)
                  (format t "data: ~a~%" data)
                  (write-socket-data socket "THIS IS A SECURE LINE!"
                                     :write-cb (lambda (socket)
                                                 (close-socket socket))))
                (lambda (ev)
                  (format t "SSL ev: ~a~%" ev)))

read-cb definition (default)
(lambda (socket byte-array) ...)

read-cb definition (when tcp-ssl-server is called with :stream t)
(lambda (socket stream) ...)

Note that in this case, stream replaces the data byte array’s position. Also, when calling :stream t in tcp-stream, the read buffer for the connecting socket is not drained and is only done so by reading from the stream.

connect-cb definition
(lambda (socket) ...)

Called when a client connects (but not necessarily when it has sent data). If present, is always called before the read-cb.

Conditions

These are the conditions the TCP SSL system can signal in event callbacks.

tcp-ssl-error

extends tcp-error

Triggered when an error happens while communicating over an SSL socket.