diff --git a/ffi.lisp b/ffi.lisp index 7aeea56..50561e3 100644 --- a/ffi.lisp +++ b/ffi.lisp @@ -253,6 +253,18 @@ :int (ctx :pointer)) +(cffi:defcenum tlsext-arg + (:nametype-hostname 0)) +(cffi:defcenum tlsext-cmd + (:set-tlsext-hostname 55)) + +(cffi:defcfun ("SSL_ctrl" ssl-ctrl) + :long + (ssl ssl-pointer) + (cmd tlsext-cmd) + (arg :int) + (parg :pointer)) + ;;; Funcall wrapper ;;; (defvar *socket*) diff --git a/streams.lisp b/streams.lisp index 56d05ca..8766029 100644 --- a/streams.lisp +++ b/streams.lisp @@ -312,10 +312,17 @@ After RELOAD, you need to call this again." (flexi-streams:make-flexi-stream stream :external-format ef) stream)) +(defun ssl-set-tlsext-hostname (stream hostname) + (ssl-ctrl stream + :set-tlsext-hostname + (cffi:foreign-enum-value 'tlsext-arg :nametype-hostname) + (cffi:convert-to-foreign hostname :string))) + + ;; fixme: free the context when errors happen in this function (defun make-ssl-client-stream (socket &key certificate key password (method 'ssl-v23-method) external-format - close-callback (unwrap-stream-p t)) + close-callback hostname (unwrap-stream-p t)) "Returns an SSL stream for the client socket descriptor SOCKET. CERTIFICATE is the path to a file containing the PEM-encoded certificate for your client. KEY is the path to the PEM-encoded key for the client, which @@ -325,6 +332,8 @@ may be associated with the passphrase PASSWORD." :socket socket :close-callback close-callback)) (handle (ssl-new *ssl-global-context*))) + (when hostname + (ssl-set-tlsext-hostname handle hostname)) (setf socket (install-handle-and-bio stream handle socket unwrap-stream-p)) (ssl-set-connect-state handle) (with-pem-password (password)