Outdated egg!
This is an egg for CHICKEN 4, the unsupported old release. You're almost certainly looking for the CHICKEN 5 version of this egg, if it exists.
If it does not exist, there may be equivalent functionality provided by another egg; have a look at the egg index. Otherwise, please consider porting this egg to the current version of CHICKEN.
openssl
Description
Bindings to the OpenSSL SSL/TLS library
Author
Requirements
- OpenSSL C library
- address-info egg
As of version 1.10.0, this egg will use the tcp6 extension if it is installed, otherwise it will fall back to the standard tcp library.
Documentation
This reference is basically a copy of the documentation of PLT Scheme's openssl module. The API provided here is largely compatible with that one. The exceptions are the missing .../enable-break and ssl-available? procedures and the missing reuse? argument to ssl-listen.
Please note that all the procedures described here may fail and raise a non-continuable exception of the composite type (exn i/o net openssl). The openssl property condition contains a property called status which will be bound to a symbol corresponding to the OpenSSL error code that was encountered. It may have the following values:
- 'zero-return
- The SSL/TLS connection was shut down unexpectedly but in a controlled way
- 'want-read
- The operation didn't finish because data must be read from a nonblocking socket. This error condition only occurs though, when it could not be handled automatically because there is actually no socket involved or some other strange thing happended in the OpenSSL library.
- 'want-write
- The operation didn't finish because data must be read from a nonblocking socket. The same comment as for 'want-read applies.
- 'want-connect
- The operation didn't finish because a nonblocking socket must first be connected. The same comment as for 'want-read applies.
- 'want-accept
- The operation didn't finish because a nonblocking socket must first be acepted. The same comment as for 'want-read applies.
- 'want-X509-lookup
- The operation failed because an application callback that could not even have been registered through this API was apparently registered anyway and has asked to be called again.
- 'syscall
- Some low-level I/O error occurred.
- 'ssl
- Something went wrong in the OpenSSL library itself.
- #f
- The error is not classified
Of course the exception that is thrown also has an appropriate message set. If you feel that this documentation lacks some information, please also consider the manual pages of OpenSSL itself.
Global parameters
For read and write timeouts, tcp-read-timeout and tcp-write-timeout are honored (from tcp6 if available, otherwise from tcp).
- ssl-handshake-timeout #!optional TIMEOUTparameter
The time in milliseconds to wait for a SSL handshake to complete (after ssl-connect or ssl-accept). Defaults to 120000, ie two minutes.
note: The handshake is only initiated after the first read or the first write action occurs on the connection, so the timer is started upon that first action.
- ssl-shutdown-timeout #!optional TIMEOUTparameter
The time in milliseconds to wait for a SSL shutdown operation to complete (after closing a port). Defaults to 120000, ie two minutes.
- ssl-default-certificate-authority-directory #!optional DIRECTORYparameter
The default directory containing trusted CA certificates that is used if verification is enabled but not explicitly configured using the convenience constructors.
Client procedures
- (ssl-connect (hostname <string>) #!optional (port <exact>) ((ctx <ssl-client-context|symbol>) 'sslv2-or-v3) (sni-name <string|bool>)) => <input-port>, <output-port>procedure
This procedure exists mainly for backwards compatibility. Consider using ssl-connect* instead, which uses better default settings.
Connect to the given hostname on the given port (a number from 1 to 65535). This connection will be encrypted using SSL. The return values are as tcp-connect; an input port and an output port.
The optional ctx 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 (see below), or one of the following symbols: 'sslv2-or-v3 (the default), 'sslv3, 'tls, 'tlsv1, 'tlsv11 or 'tlsv12. See ssl-make-client-context for further details, including the meanings of the protocol symbols.
The optional sni-name argument determines whether a virtual hostname is sent with the connection handshake: If sni-name is a string, that value is sent as the virtual hostname. If sni-name is #t and the value of hostname does not look like a literal IPv4 or IPv6 address, it is sent as the virtual hostname. By default, no virtual hostname is sent.
- (ssl-connect* #!key (hostname <string>) (port <exact>) ((sni-name <string|bool>) #t) ((protocol <symbol>) 'tlsv12) ((cipher-list <any>) "DEFAULT") (certificate <string|blob>) (private-key <string|blob>) ((private-key-type <symbol>) 'rsa) (private-key-asn1? <bool>) (certificate-authorities <string>) (certificate-authority-directory <string>) ((verify? <bool>) #t)) => <input-port>, <output-port>procedure
Convenience constructor for SSL connections that uses keyword arguments to convey client context initialization information. Uses sensible defaults for the protocol configuration, enables certificate verification and sends a virtual hostname by default.
The hostname and port arguments determine the network address to connect to. See ssl-make-client-context* for a description of the other keyword arguments.
- (ssl-make-client-context #!optional ((protocol <symbol>) 'sslv2-or-v3)) => <ssl-client-context>procedure
This procedure exists mainly for backwards compatibility. Consider using ssl-make-client-context* instead, which uses better default settings.
Creates a context to be supplied to ssl-connect. The context identifies a communication protocol (as selected by protocol), and also holds certificate information (i.e., the client's identity, its trusted certificate authorities, etc.). See the "Certificate procedures" section below for more information on certificates.
The protocol must be one of the following:
- 'sslv2-or-v3
- TLS protocol or SSL protocol versions 2 or 3, as appropriate
- 'sslv3
- SSL protocol version 3
- 'tls or 'tlsv1
- the TLS protocol version 1
- 'tlsv11
- the TLS protocol version 1.1
- 'tlsv12
- the TLS protocol version 1.2
The default protocol is 'sslv2-or-v3, which ensures maximum compatibility with other endpoints. Note, however, that this choice is not particularly secure. Vulnerabilities affecting only the legacy protocols can be avoided by explicitly requesting the 'tls protocol, if every peer you will be communicating with is supporting this.
By default, the context returned by ssl-make-client-context does not request verification of a server's certificate. Use ssl-set-verify! to enable such verification.
- (ssl-make-client-context* #!key ((protocol <symbol>) 'tlsv12) ((cipher-list <any>) "DEFAULT") (certificate <string|blob>) (private-key <string|blob>) ((private-key-type <symbol>) 'rsa) (private-key-asn1? <bool>) (certificate-authorities <string>) (certificate-authority-directory <string>) ((verify? <bool>) #t)) => <ssl-client-context>procedure
Convenience constructor for client contexts that uses keyword arguments to convey initialization information. Uses sensible defaults for the protocol configuration and enables certificate verification.
The protocol can be any of the choices available for ssl-make-client-context, but it defaults to the modern 'tlsv12. You can customize the list of allowed cipher suites using the cipher-list argument, which is passed to ssl-set-cipher-list!. A client certificate and associated private key can be loaded using the certificate and private-key arguments, which may be strings representing file paths or blobs containing the data itself; see ssl-load-certificate-chain! and ssl-load-private-key! for details. The verification of server certificates may be enabled (the default) or disabled using verify?; the set of trusted CA certificates can be specified by certificate-authorities and certificate-authority-directory, which are passed to ssl-load-verify-root-certificates!.
- (ssl-client-context? (obj <top>)) => <bool>procedure
Returns #t if obj is a value produced by ssl-make-client-context or ssl-make-client-context*, #f otherwise.
Server procedures
- (ssl-listen (port <exact>) #!optional ((backlog <exact>) 4) ((hostname <string>) #f) ((ctx <ssl-client-context|symbol>) 'sslv2-or-v3)) => <ssl-listener>procedure
This procedure exists mainly for backwards compatibility. Consider using ssl-listen* instead, which uses better default settings.
Like tcp-listen, but the result is an SSL listener. The extra optional ctx argument is as for ssl-connect.
The default protocol is 'sslv2-or-v3, which ensures maximum compatibility with clients. Note, however, that this choice is not particularly secure. Vulnerabilities affecting only the legacy protocols can be avoided by explicitly requesting the 'tls protocol, if every client that will connect to the server is supporting this.
Call ssl-load-certificate-chain! and ssl-load-private-key! to avoid a "no shared cipher" error on accepting connections.
- (ssl-listen* #!key (hostname <string>) ((port <exact>) 0) ((backlog <exact>) 4) ((protocol <symbol>) 'tlsv12) ((cipher-list <any>) "DEFAULT") (certificate <string|blob>) (private-key <string|blob>) ((private-key-type <symbol>) 'rsa) (private-key-asn1? <bool>) (certificate-authorities <string>) (certificate-authority-directory <string>) ((verify? <bool>) #f)) => <ssl-listener>procedure
Convenience constructor for an SSL listener that uses keyword arguments to convey initialization information. Uses sensible defaults for the protocol configuration.
The hostname argument determines the local network interface to listen on and defaults to the wildcard address. The port arguments determine the local network port to listen to and defaults to a randomly selected port. The protocol can be any of the choices available for ssl-listen, but it defaults to the modern 'tlsv12. You can customize the list of allowed cipher suites using the cipher-list argument, which is passed to ssl-set-cipher-list!. A server certificate and associated private key can be loaded using the certificate and private-key arguments, which may be strings representing file paths or blobs containing the data itself; see ssl-load-certificate-chain! and ssl-load-private-key! for details. The verification of client certificates may be enabled or disabled (the default) using verify?; the set of trusted CA certificates can be specified by certificate-authorities and certificate-authority-directory, which are passed to ssl-load-verify-root-certificates!.
- (ssl-close (listener <ssl-listener>)) => <void>procedure
- (ssl-listener? (obj <top>)) => <bool>procedure
- (ssl-listener-port (listener <ssl-listener>)) => <exact>procedure
- (ssl-listener-fileno (listener <ssl-listener>)) => <exact>procedure
- (ssl-listener-accept-ready? (listener <ssl-listener>)) => <bool>procedure
- (ssl-accept (listener <ssl-listener>)) => <input-port>, <output-port>procedure
Analogous to tcp-close, tcp-listener?, tcp-listener-port, tcp-listener-fileno, tcp-accept-ready? and tcp-accept.
STARTTLS support
- (ssl-start* (server? <bool>) (sni-name <string>) (tcp-in <input-port>) (tcp-out <output-port>) #!key ((protocol <symbol>) 'tlsv12) ((cipher-list <any>) "DEFAULT") (certificate <string|blob>) (private-key <string|blob>) ((private-key-type <symbol>) 'rsa) (private-key-asn1? <bool>) (certificate-authorities <string>) (certificate-authority-directory <string>) ((verify? <bool>) (not server?))) => <input-port>, <output-port>procedure
Given existing TCP input and output ports, ssl-start* establishes an SSL context working on top of the TCP connection. The returned ports should be used for all further communication with the remote peer. ssl-start* acts similar to ssl-connect* if server? is false or to ssl-accept if server? is true. The arguments all behave analogous to those for ssl-connect* or ssl-listen*.
Certificate procedures
- (ssl-load-certificate-chain! (obj <ssl-client-context|ssl-listener>) (pathname/blob <string|blob>)) => <void>procedure
Loads a PEM-format certification chain file or data blob for connections to be made with the given context (created by ssl-make-context) or listener (created by ssl-listener).
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.
- (ssl-load-private-key! (obj <ssl-client-context|ssl-listener>) (pathname/blob <string|blob>) #!optional ((rsa? <symbol|bool>) #t) ((asn1? <bool>) #f)) => <void>procedure
Loads the first private key from the file or data blob pathname/blob for the given client context or listener. The key goes with the certificate that identifies the client or server.
If rsa? is #t or 'rsa, the first RSA key is read (i.e., non-RSA keys are skipped). If rsa? is #f or 'dsa, a DSA key is read.
If pathname/blob is a data blob, the key must be ASN1 encoded and rsa? may also take the values 'dh or 'ec to load Diffie-Hellman or Elliptic Curve keys respectively.
If asn1? is #t and pathname/blob refers to a file, that file is parsed as ASN1 format instead of PEM.
- (ssl-set-verify! (obj <ssl-client-context|ssl-listener>) (v <bool>)) => <void>procedure
Enables or disables verification of a connection peer's certificates. By default, verification is disabled.
Enabling verification also requires, at a minimum, designating trusted certificate authorities with ssl-load-verify-root-certificates!.
- (ssl-load-verify-root-certificates! (obj <ssl-client-context|ssl-listener>) (pathname <string>) #!optional ((dirname <string>) #f)) => <void>procedure
Loads a PEM-format file containing trusted certificates that are used to verify the certificates of a connection peer. Call this procedure multiple times to load multiple sets of trusted certificates.
The optional second argument specifies a directory in which certificates are automatically looked up. You may also only pass a path in this argument and pass #f as the first argument to this procedure. See the OpenSSL documentation on SSL_CTX_load_verify_locations for more details.
- (ssl-load-suggested-certificate-authorities! (obj <ssl-client-context|ssl-listener>) (pathname <string>)) => <void>procedure
Loads a PEM-format file containing certificates that are used by a server. The certificate list is sent to a client when the server requests a certificate as an indication of which certificates the server trusts.
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!.
Cipher selection
- (ssl-set-cipher-list! (obj <ssl-client-context|ssl-listener>) (v <any>)) => <void>procedure
Selects a list of allowed cipher suites that are used by an SSL client or server.
The given value v may be a string such as "DEFAULT"; the format of strings accepted by the OpenSSL library is described in its ciphers(1) manual page. If you pass a list as v, its elements are joined by ":" characters. Any other value for v and any list elements are converted to strings using ->string.
Port procedures
- ssl-port? objprocedure
Predicate for SSL ports; returns #t if obj is an SSL port, #f if it isn't.
- ssl-port->tcp-port pprocedure
Convert SSL port p to the raw underlying TCP port.
This is mostly useful if you need to obtain extra information about the connection, like for example tcp-addresses. Note that you generally cannot safely send data over the port, as that would interfere with OpenSSL's operation.
Changelog
- 1.10.0 Use the tcp6 egg when it is present to allow binding to IPv6 interfaces or connecting to IPv6 hosts.
- 1.9.4 Improved block I/O performance thanks to TheLemonMan
- 1.9.2 Use address-info to choose default SNI behaviour
- 1.9.1 Add client-side SNI support
- 1.8.0 Add ssl-start* to support layering SSL on top of an existing TCP connection
- 1.7.0 Various improvements including CHICKEN 4.10 compatibility and new constructors with more secure defaults
- 1.6.2 Correct read-byte of chars with high bit set; fixes #954
- 1.5.1 Small bugfixes by Mario Domenech Goulart
- 1.5 Do not let ssl-accept or ssl-connect block immediately but defer it until reading or writing to the ports. Add ssl-handshake-timeout and ssl-shutdown-timeout options.
- 1.4 Fix intermittent bug in ssl-write caused by the GC's moving around of memory locations
- 1.3 Make ssl ports completely distinct from tcp ports. Add ssl-port? and ssl-port->tcp-port procedures.
- 1.1.7 fix for vector deref crash (elf, reported by glogic)
- 1.1.6 windows linking fixes by Alex Queiroz
- 1.1.5 added static linking support [felix]
- 1.1.4 fixed problems with the shutdown sequence
- 1.1.3 fixes problem with older chickens and missing newline before `<#' in blocks of foreign code [Thanks to Dan Muresan]
- 1.1.2 uses foreign-code macro insead of obsolete read syntax
- 1.1.1 Output that would block properly suspends threads now
- 1.1.0 ##sys#tcp-port->fileno and tcp-addresses are now supported on SSL ports
- 1.0.0 Corrections, tests against openssl s_server, openssl s_client and comparison with the PLT module
- 0.4.0 Server functionality added
- 0.3.1 Client-only with certificate functions
- 0.2.0 Client-only prerelease
License
Copyright (c) 2005, Thomas Chust <chust@web.de>. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the author nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.