OpenSSL: Secure Communication
(require openssl) |
The openssl library provides glue for the OpenSSL library with the Racket port system. It provides functions nearly identically to the standard TCP subsystem in Racket, plus a generic ports->ssl-ports interface.
To use this library, you will need OpenSSL installed on your machine, but on many platforms the necessary libraries are included with the OS or with the Racket distribution. In particular:
For Windows, openssl depends on "libeay32.dll" and "ssleay32.dll", which are included in the Racket distribution for Windows.
For Mac OS X, openssl depends on "libssl.dylib" and "libcrypto.dylib", which are provided by Mac OS X 10.2 and later.
For Unix, openssl depends on "libssl.so" and "libcrypto.so", which must be installed in a standard library location or in a directory listed by LD_LIBRARY_PATH. These libraries are included in many OS distributions.
value
value
ssl-load-fail-reason : (or/c #f string?)
1 TCP-like Client Procedures
Use ssl-connect or ssl-connect/enable-break to create an SSL connection over TCP. To create a secure connection, supply the result of ssl-secure-client-context or create a client context with ssl-make-client-context and configure it using the functions described in Context Procedures.
procedure
(ssl-connect hostname port-no [ client-protocol]) →
input-port? output-port? hostname : string? port-no : (integer-in 1 65535)
client-protocol :
(or/c ssl-client-context? 'sslv2-or-v3 'sslv2 'sslv3 'tls) = 'sslv2-or-v3
The optional client-protocol argument determines which encryption protocol is used, whether the server’s certificate is checked, etc. The argument can be either a client context created by ssl-make-client-context, or one of the following symbols: 'sslv2-or-v3 (the default), 'sslv2, 'sslv3, or 'tls; see ssl-make-client-context for further details (including the meanings of the protocol symbols).
Closing the resulting output port does not send a shutdown message to the server. See also ports->ssl-ports.
If hostname verification is enabled (see ssl-set-verify-hostname!), the peer’s certificate is checked against hostname.
procedure
(ssl-connect/enable-break hostname port-no [ client-protocol])
→
input-port? output-port? hostname : string? port-no : (integer-in 1 65535)
client-protocol : (or/c ssl-client-context? 'sslv2-or-v3 'sslv2 'sslv3 'tls) = 'sslv2-or-v3
procedure
(let ([ctx (ssl-make-client-context 'tls)]) ; Load default verification sources (root certificates) (ssl-load-default-verify-sources! ctx) ; Require certificate verification (ssl-set-verify! ctx #t) ; Require hostname verification (ssl-set-verify-hostname! ctx #t) ; No weak cipher suites (ssl-set-ciphers! ctx "DEFAULT:!aNULL:!eNULL:!LOW:!EXPORT:!SSLv2") ; Seal context so further changes cannot weaken it (ssl-seal-context! ctx) ctx)
The context is cached, so different calls to ssl-secure-client-context return the same context unless (ssl-default-verify-sources) has changed.
procedure
(ssl-make-client-context [protocol]) → ssl-client-context?
protocol : (or/c 'sslv2-or-v3 'sslv2 'sslv3 'tls) = 'sslv2-or-v3
'sslv2-or-v3 : SSL protocol versions 2 or 3, as appropriate (this is the default)
'sslv2 : SSL protocol version 2
'sslv3 : SSL protocol version 3
'tls : the TLS protocol version 1
Note that SSL protocol version 2 is deprecated on some platforms and may not be present in your system libraries. The use of SSLv2 may also compromise security; thus, using SSLv3 is recommended.
procedure
(ssl-client-context? v) → boolean?
v : any/c
2 TCP-like Server Procedures
procedure
(ssl-listen port-no [ queue-k reuse? hostname-or-#f server-protocol]) → ssl-listener? port-no : (integer-in 1 65535) queue-k : exact-nonnegative-integer? = 5 reuse? : any/c = #f hostname-or-#f : (or/c string? #f) = #f
server-protocol : (or/c ssl-server-context? 'sslv2-or-v3 'sslv2 'sslv3 'tls) = 'sslv2-or-v3
Call ssl-load-certificate-chain! and ssl-load-private-key! to avoid a no shared cipher error on accepting connections. The file "test.pem" in the "openssl" collection is a suitable argument for both calls when testing. Since "test.pem" is public, however, such a test configuration obviously provides no security.
An SSL listener is a synchronizable value (see sync). It is
ready—
procedure
listener : ssl-listener?
procedure
(ssl-listener? v) → boolean?
v : any/c
procedure
(ssl-accept listener) →
input-port? output-port? listener : ssl-listener?
procedure
(ssl-accept/enable-break listener) →
input-port? output-port? listener : ssl-listener?
Closing the resulting output port does not send a shutdown message to the client. See also ports->ssl-ports.
See also ssl-connect about the limitations of reading and writing to an SSL connection (i.e., one direction at a time).
The ssl-accept/enable-break procedure is analogous to tcp-accept/enable-break.
procedure
(ssl-abandon-port in) → void?
in : (and/c ssl-port? output-port?)
procedure
(ssl-addresses p [port-numbers?]) → void?
p : (or/c ssl-port? ssl-listener?) port-numbers? : any/c = #f
procedure
(ssl-make-server-context protocol) → ssl-server-context?
protocol : (or/c 'sslv2-or-v3 'sslv2 'sslv3 'tls)
procedure
(ssl-server-context? v) → boolean?
v : any/c
3 SSL-wrapper Interface
procedure
(ports->ssl-ports input-port output-port [ #:mode mode #:context context #:encrypt protocol #:close-original? close-original? #:shutdown-on-close? shutdown-on-close? #:error/ssl error #:hostname hostname])
→
input-port? output-port? input-port : input-port? output-port : output-port? mode : symbol? = 'accept
context : (or/c ssl-client-context? ssl-server-context?) =
((if (eq? mode 'accept) ssl-make-server-context ssl-make-client-context) protocol)
protocol : (or/c 'sslv2-or-v3 'sslv2 'sslv3 'tls) = 'sslv2-or-v3 close-original? : boolean? = #f shutdown-on-close? : boolean? = #f error : procedure? = error hostname : (or/c string? #f) = #f
The mode argument can be 'connect or 'accept. The mode determines how the SSL protocol is initialized over the ports, either as a client or as a server. As with ssl-listen, in 'accept mode, supply a context that has been initialized with ssl-load-certificate-chain! and ssl-load-private-key! to avoid a no shared cipher error.
The context argument should be a client context for 'connect mode or a server context for 'accept mode. If it is not supplied, a context is created using the protocol specified by a protocol argument.
If the protocol argument is not supplied, it defaults to 'sslv2-or-v3. See ssl-make-client-context for further details (including all options and the meanings of the protocol symbols). This argument is ignored if a context argument is supplied.
If close-original? is true, then when both SSL ports are closed, the given input and output ports are automatically closed.
If shutdown-on-close? is true, then when the output SSL port is closed, it sends a shutdown message to the other end of the SSL connection. When shutdown is enabled, closing the output port can fail if the given output port becomes unwritable (e.g., because the other end of the given port has been closed by another process).
The error argument is an error procedure to use for raising communication errors. The default is error, which raises exn:fail; in contrast, ssl-accept and ssl-connect use an error function that raises exn:fail:network.
See also ssl-connect about the limitations of reading and writing to an SSL connection (i.e., one direction at a time).
If hostname verification is enabled (see ssl-set-verify-hostname!), the peer’s certificate is checked against hostname.
4 Context Procedures
procedure
(ssl-load-verify-source! context src [ #:try? try?]) → void? context : (or/c ssl-client-context? ssl-server-context?)
src :
(or/c path-string? (list/c 'directory path-string?) (list/c 'win32-store string?) (list/c 'macosx-keychain path-string?)) try? : any/c = #f
The following kinds of verification sources are supported:
If src is a path or string, it is treated as a PEM file containing root certificates. The file is loaded immediately.
If src is (list 'directory dir), then dir should contain PEM files with hashed symbolic links (see the openssl c_rehash utility). The directory contents are not loaded immediately; rather, they are searched only when a certificate needs verification.
If src is (list 'win32-store store), then the certificates from the store named store are loaded immediately. Only supported on Windows.
If src is (list 'macosx-keychain path), then the certificates from the keychain stored at path are loaded immediately. Only supported on Mac OS X.
If try? is #f and loading src fails (for example, because the file or directory does not exist), then an exception is raised. If try? is a true value, then a load failure is ignored.
You can use the file "test.pem" of the "openssl" collection for testing purposes. Since "test.pem" is public, such a test configuration obviously provides no security.
parameter
→
(let ([source/c (or/c path-string? (list/c 'directory path-string?) (list/c 'win32-store string?) (list/c 'macosx-keychain path-string?))]) (listof source/c)) (ssl-default-verify-sources srcs) → void?
srcs :
(let ([source/c (or/c path-string? (list/c 'directory path-string?) (list/c 'win32-store string?) (list/c 'macosx-keychain path-string?))]) (listof source/c))
On Linux, the default sources are determined by the SSL_CERT_FILE and SSL_CERT_DIR environment variables, if the variables are set, or the system-wide default locations otherwise.
On Mac OS X, the default sources consist of the system keychain for root certificates: '(macosx-keychain "/System/Library/Keychains/SystemRootCertificates.keychain").
On Windows, the default sources consist of the system certificate store for root certificates: '(win32-store "ROOT").
procedure
(ssl-load-default-verify-sources! context) → void?
context : (or/c ssl-client-context? ssl-server-context?)
procedure
(ssl-load-verify-root-certificates! context-or-listener pathname) → void?
context-or-listener :
(or/c ssl-client-conntext? ssl-server-context? ssl-listener?) pathname : path-string?
procedure
(ssl-set-ciphers! context cipher-spec) → void?
context : (or/c ssl-client-context? ssl-server-context?) cipher-spec : string?
procedure
(ssl-seal-context! context) → void?
context : (or/c ssl-client-context? ssl-server-context?)
procedure
(ssl-load-certificate-chain! context-or-listener pathname) → void?
context-or-listener :
(or/c ssl-client-context? ssl-server-context? ssl-listener?) pathname : path-string?
This chain is used to identify the client or server when it connects or accepts connections. Loading a chain overwrites the old chain. Also call ssl-load-private-key! to load the certificate’s corresponding key.
You can use the file "test.pem" of the "openssl" collection for testing purposes. Since "test.pem" is public, such a test configuration obviously provides no security.
procedure
(ssl-load-private-key! context-or-listener pathname [ rsa? asn1?]) → void?
context-or-listener :
(or/c ssl-client-context? ssl-server-context? ssl-listener?) pathname : path-string? rsa? : boolean? = #t asn1? : boolean? = #f
If rsa? is #t (the default), the first RSA key is read (i.e., non-RSA keys are skipped). If asn1? is #t, the file is parsed as ASN1 format instead of PEM.
You can use the file "test.pem" of the "openssl" collection for testing purposes. Since "test.pem" is public, such a test configuration obviously provides no security.
procedure
(ssl-load-suggested-certificate-authorities! context-or-listener pathname) → void?
context-or-listener :
(or/c ssl-client-context? ssl-server-context? ssl-listener?) pathname : path-string?
Loading the suggested certificates does not imply trust, however; any certificate presented by the client will be checked using the trusted roots loaded by ssl-load-verify-root-certificates!.
You can use the file "test.pem" of the "openssl" collection for testing purposes where the peer identifies itself using "test.pem".
5 Peer Verification
procedure
(ssl-set-verify! clp on?) → void?
clp :
(or/c ssl-client-context? ssl-server-context? ssl-listener? ssl-port?) on? : any/c
Enabling verification also requires, at a minimum, designating trusted certificate authorities with ssl-load-verify-source!.
Verifying the certificate is not sufficient to prevent attacks by active adversaries, such as man-in-the-middle attacks. See also ssl-set-verify-hostname!.
procedure
(ssl-try-verify! clp on?) → void?
clp :
(or/c ssl-client-context? ssl-server-context? ssl-listener? ssl-port?) on? : any/c
procedure
(ssl-peer-verified? p) → boolean?
p : ssl-port?
procedure
(ssl-set-verify-hostname! ctx on?) → void?
ctx : (or/c ssl-client-context? ssl-server-context?) on? : any/c
Hostname verification does not imply certificate verification. To verify the certificate itself, also call ssl-set-verify!.
procedure
p : ssl-port?
The result list may contain both hostnames such as "www.racket-lang.org" and hostname patterns such as "*.racket-lang.org".
procedure
(ssl-peer-check-hostname p hostname) → boolean?
p : ssl-port? hostname : string?
procedure
(ssl-peer-subject-name p) → (or/c bytes? #f)
p : ssl-port?
Use ssl-peer-check-hostname or ssl-peer-certificate-hostnames instead to check the validity of an SSL connection.
procedure
(ssl-peer-issuer-name p) → (or/c bytes? #f)
p : ssl-port?
6 SHA-1 Hashing
The sha1 function composes bytes->hex-string with sha1-bytes.
procedure
(sha1-bytes in) → bytes?
in : input-port
procedure
(bytes->hex-string bstr) → string?
bstr : bytes?