update docs

This commit is contained in:
Ryan Culpepper 2012-11-24 16:07:25 -05:00
parent dc2a63182d
commit 9a07eed458

View File

@ -1,8 +1,7 @@
#lang scribble/doc
@(require scribble/manual
scribble/bnf
(for-label openssl
scheme
racket
openssl/sha1))
@title{OpenSSL: Secure Communication}
@ -15,21 +14,27 @@ identically to the standard TCP subsystem in Racket, plus a
generic @racket[ports->ssl-ports] interface.
To use this library, you will need OpenSSL installed on your machine,
but
but on many platforms the necessary libraries are included with the OS
or with the Racket distribution. In particular:
@itemize[
@item{for Windows, the Racket distribution for Windows includes
the necessary DLLs.}
@item{for Mac OS X, version 10.2 and later provides the necessary
OpenSSL libraries.}
@item{For Windows, @racketmodname[openssl] depends on
@filepath{libeay32.dll} and @filepath{ssleay32.dll}, which are
included in the Racket distribution for Windows.}
@item{for Unix, @filepath{libssl.so} and @filepath{libcrypto.so} are
likely to be installed on your machine, already.}
@item{For Mac OS X, @racketmodname[openssl] depends on
@filepath{libssl.dylib} and @filepath{libcrypto.dylib}, which are
provided by Mac OS X 10.2 and later.}
@item{For Unix, @racketmodname[openssl] depends on
@filepath{libssl.so} and @filepath{libcrypto.so}, which must be
installed in a standard library location or in a directory listed by
@envvar{LD_LIBRARY_PATH}. These libraries are included in many OS
distributions.}
]
@defthing[ssl-available? boolean?]{
A boolean value which says whether the system openssl library was
@ -37,48 +42,30 @@ successfully loaded. Calling @racket[ssl-connect], @|etc| when this
value is @racket[#f] (library not loaded) will raise an exception.}
@defthing[ssl-load-fail-reason (or/c false/c string?)]{
@defthing[ssl-load-fail-reason (or/c #f string?)]{
Either @racket[#f] (when @racket[ssl-available?] is @racket[#t]) or an
error string (when @racket[ssl-available?] is @racket[#f]).}
@; ----------------------------------------------------------------------
@section{Using SSL Securely}
SSL and TLS are client-server cryptographic protocols that enable
secure communication with remote hosts (called ``peers''). But SSL
must be properly configured in order to be secure.
The security of client programs using SSL generally depends
on the authentication of the server credentials, which requires proper
initialization of this library's client contexts. To use SSL securely,
a client program must at a minimum take the following steps:
@itemlist[
@item{create an SSL client context using @racket[ssl-make-client-context]}
@item{tell the context what certificate authorities to trust using
@racket[ssl-load-verify-root-certificates!]}
@item{turn on certificate verification using @racket[ssl-set-verify!]
(or check each connection individually using @racket[ssl-peer-verified?])}
@item{turn on hostname verification using
@racket[ssl-set-verify-hostname!] (or check each connection
individually using @racket[ssl-peer-check-hostname])}
]
@; ----------------------------------------------------------------------
@section{TCP-like Client Procedures}
@defproc[(ssl-connect (hostname string?)
(port-no (integer-in 1 65535))
(client-protocol
(or/c ssl-client-context? symbol?) 'sslv2-or-v3))
Use @racket[ssl-connect] or @racket[ssl-connect/enable-break] to
create an SSL connection over TCP. To create a secure connection,
supply the result of @racket[ssl-secure-client-context] or create a
client context with @racket[ssl-make-client-context] and configure it
using the functions described in @secref["cert-procs"].
@defproc[(ssl-connect [hostname string?]
[port-no (integer-in 1 65535)]
[client-protocol
(or/c ssl-client-context?
'sslv2-or-v3
'sslv2
'sslv3
'tls)
'sslv2-or-v3])
(values input-port? output-port?)]{
Connect to the host given by @racket[hostname], on the port given by
@ -119,17 +106,49 @@ whether the other end is supposed to be sending or reading data.
}
@defproc[(ssl-connect/enable-break
(hostname string?)
(port-no (integer-in 1 65535))
(client-protocol
(or/c ssl-client-context? symbol?) 'sslv2-or-v3))
[hostname string?]
[port-no (integer-in 1 65535)]
[client-protocol
(or/c ssl-client-context? 'sslv2-or-v3 'sslv2 'sslv3 'tls)
'sslv2-or-v3])
(values input-port? output-port?)]{
Like @racket[ssl-connect], but breaking is enabled while trying to
connect.}
@defproc[(ssl-make-client-context (protocol symbol? 'sslv2-or-v3))
@defproc[(ssl-secure-client-context)
ssl-client-context?]{
Returns a client context (using the @racket['tls] protocol) that
verifies certificates using the default verification sources from
@racket[(ssl-default-verify-sources)], verifies hostnames, and avoids
using weak ciphers. The result is essentially equivalent to the
following:
@racketblock[
(let ([ctx (ssl-make-client-context 'tls)])
(code:comment "Load default verification sources (root certificates)")
(ssl-load-default-verify-sources! ctx)
(code:comment "Require certificate verification")
(ssl-set-verify! ctx #t)
(code:comment "Require hostname verification")
(ssl-set-verify-hostname! ctx #t)
(code:comment "No weak cipher suites")
(ssl-set-ciphers! ctx "DEFAULT:!aNULL:!eNULL:!LOW:!EXPORT:!SSLv2")
(code:comment "Seal context so further changes cannot weaken it")
(ssl-seal-context! ctx)
ctx)
]
The context is cached, so different calls to
@racket[ssl-secure-client-context] return the same context unless
@racket[(ssl-default-verify-sources)] has changed.
}
@defproc[(ssl-make-client-context
[protocol (or/c 'sslv2-or-v3 'sslv2 'sslv3 'tls) 'sslv2-or-v3])
ssl-client-context?]{
Creates a context to be supplied to @racket[ssl-connect]. The context
@ -151,25 +170,10 @@ The @racket[protocol] must be one of the following:
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.
By default, the context returned by @racket[ssl-make-client-context] does not
request verification of a server's certificate. Use @racket[ssl-set-verify!]
to enable such verification.}
@defproc[(ssl-secure-client-context)
ssl-client-context?]{
Returns a client context (using @racket['tls]) that verifies
certificates using the root certificates from
@racket[(ssl-default-verify-sources)], verifies hostnames, and
avoids using weak ciphers. The context is sealed to prevent further
modification, and the context is cached, so different calls to
@racket[ssl-secure-client-context] return the same context unless
@racket[(ssl-default-verify-sources)] has changed.
}
@defproc[(ssl-client-context? (v any/c)) boolean?]{
@defproc[(ssl-client-context? [v any/c]) boolean?]{
Returns @racket[#t] if @racket[v] is a value produced by
@racket[ssl-make-client-context], @racket[#f] otherwise.}
@ -180,12 +184,13 @@ Returns @racket[#t] if @racket[v] is a value produced by
@section{TCP-like Server Procedures}
@defproc[(ssl-listen
(port-no (integer-in 1 65535))
[queue-k exact-nonnegative-integer?]
[port-no (integer-in 1 65535)]
[queue-k exact-nonnegative-integer? 5]
[reuse? any/c #f]
[hostname-or-#f (or/c string? false/c) #f]
[hostname-or-#f (or/c string? #f) #f]
[server-protocol
(or/c ssl-server-context? symbol?) 'sslv2-or-v3])
(or/c ssl-server-context? 'sslv2-or-v3 'sslv2 'sslv3 'tls)
'sslv2-or-v3])
ssl-listener?]{
Like @racket[tcp-listen], but the result is an SSL listener. The extra optional
@ -207,15 +212,15 @@ further communication is needed to establish the connection.}
@deftogether[(
@defproc[(ssl-close (listener ssl-listener?)) void?]
@defproc[(ssl-listener? (v any/c)) boolean?])]{
@defproc[(ssl-close [listener ssl-listener?]) void?]
@defproc[(ssl-listener? [v any/c]) boolean?])]{
Analogous to @racket[tcp-close] and @racket[tcp-listener?].}
@deftogether[(
@defproc[(ssl-accept (listener ssl-listener?))
@defproc[(ssl-accept [listener ssl-listener?])
(values input-port? output-port?)]
@defproc[(ssl-accept/enable-break (listener ssl-listener?))
@defproc[(ssl-accept/enable-break [listener ssl-listener?])
(values input-port? output-port?)])]{
Analogous to @racket[tcp-accept].
@ -235,7 +240,9 @@ The @racket[ssl-accept/enable-break] procedure is analogous to
Analogous to @racket[tcp-abandon-port].}
@defproc[(ssl-addresses [p (or/c ssl-port? ssl-listener?)][port-numbers? any/c #f]) void?]{
@defproc[(ssl-addresses [p (or/c ssl-port? ssl-listener?)]
[port-numbers? any/c #f])
void?]{
Analogous to @racket[tcp-addresses].}
@ -248,12 +255,12 @@ Returns @racket[#t] of @racket[v] is an SSL port produced by
@racket[ports->ssl-ports].}
@defproc[(ssl-make-server-context (protocol symbol?))
@defproc[(ssl-make-server-context [protocol (or/c 'sslv2-or-v3 'sslv2 'sslv3 'tls)])
ssl-server-context?]{
Like @racket[ssl-make-client-context], but creates a server context.}
@defproc[(ssl-server-context? (v any/c)) boolean?]{
@defproc[(ssl-server-context? [v any/c]) boolean?]{
Returns @racket[#t] if @racket[v] is a value produced by
@racket[ssl-make-server-context], @racket[#f] otherwise.}
@ -264,15 +271,16 @@ Returns @racket[#t] if @racket[v] is a value produced by
@section{SSL-wrapper Interface}
@defproc[(ports->ssl-ports
(input-port input-port?)
(output-port output-port?)
[input-port input-port?]
[output-port output-port?]
[#:mode mode symbol? 'accept]
[#:context context (or/c ssl-client-context? ssl-server-context?)
[#:context context
(or/c ssl-client-context? ssl-server-context?)
((if (eq? mode 'accept)
ssl-make-server-context
ssl-make-client-context)
protocol)]
[#:encrypt protocol symbol? 'sslv2-or-v3]
[#:encrypt protocol (or/c 'sslv2-or-v3 'sslv2 'sslv3 'tls) 'sslv2-or-v3]
[#:close-original? close-original? boolean? #f]
[#:shutdown-on-close? shutdown-on-close? boolean? #f]
[#:error/ssl error procedure? error]
@ -332,46 +340,6 @@ against @racket[hostname].
@section[#:tag "cert-procs"]{Context Procedures}
@defproc[(ssl-load-certificate-chain!
(context-or-listener (or/c ssl-client-context? ssl-server-context?
ssl-listener?))
(pathname path-string?))
void?]{
Loads a PEM-format certification chain file for connections to made
with the given context (created by @racket[ssl-make-client-context] or
@racket[ssl-make-server-context]) or listener (created by
@racket[ssl-listen]).
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 @racket[ssl-load-private-key!] to load the certificate's
corresponding key.
You can use the file @filepath{test.pem} of the @filepath{openssl}
collection for testing purposes. Since @filepath{test.pem} is public,
such a test configuration obviously provides no security.}
@defproc[(ssl-load-private-key!
(context-or-listener (or/c ssl-client-context? ssl-server-context?
ssl-listener?))
(pathname path-string?)
[rsa? boolean? #t]
[asn1? boolean? #f])
void?]{
Loads the first private key from @racket[pathname] for the given
context or listener. The key goes with the certificate that identifies
the client or server.
If @racket[rsa?] is @racket[#t] (the default), the first RSA key is
read (i.e., non-RSA keys are skipped). If @racket[asn1?] is
@racket[#t], the file is parsed as ASN1 format instead of PEM.
You can use the file @filepath{test.pem} of the @filepath{openssl}
collection for testing purposes. Since @filepath{test.pem} is public,
such a test configuration obviously provides no security.}
@defproc[(ssl-load-verify-source!
[context (or/c ssl-client-context? ssl-server-context?)]
[src (or/c path-string?
@ -381,7 +349,7 @@ such a test configuration obviously provides no security.}
void?]{
Loads verification sources from @racket[src] into
@racket[context]. Currently, only root certificates are loaded; the
@racket[context]. Currently, only certificates are loaded; the
certificates are used to verify the certificates of a connection
peer. Call this procedure multiple times to load multiple sets of
trusted certificates.
@ -457,25 +425,6 @@ Deprecated; like @racket[ssl-load-verify-source!], but only supports
loading certificate files in PEM format.
}
@defproc[(ssl-load-suggested-certificate-authorities!
(context-or-listener (or/c ssl-client-context? ssl-server-context?
ssl-listener?))
(pathname path-string?))
void?]{
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 @racket[ssl-load-verify-root-certificates!].
You can use the file @filepath{test.pem} of the @filepath{openssl}
collection for testing purposes where the peer identifies itself using
@filepath{test.pem}.}
@defproc[(ssl-set-ciphers! [context (or/c ssl-client-context? ssl-server-context?)]
[cipher-spec string?])
void?]{
@ -495,14 +444,80 @@ context is sealed, passing it to functions such as
@racket[ssl-set-verify!] and
@racket[ssl-load-verify-root-certificates!] results in an error.}
@defproc[(ssl-load-certificate-chain!
[context-or-listener (or/c ssl-client-context? ssl-server-context?
ssl-listener?)]
[pathname path-string?])
void?]{
Loads a PEM-format certification chain file for connections to made
with the given server context (created by
@racket[ssl-make-server-context]) or listener (created by
@racket[ssl-listen]). A certificate chain can also be loaded into a
client context (created by @racket[ssl-make-client-context]) when
connecting to a server requiring client credentials, but that
situation is uncommon.
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 @racket[ssl-load-private-key!] to load the certificate's
corresponding key.
You can use the file @filepath{test.pem} of the @filepath{openssl}
collection for testing purposes. Since @filepath{test.pem} is public,
such a test configuration obviously provides no security.
}
@defproc[(ssl-load-private-key!
[context-or-listener (or/c ssl-client-context? ssl-server-context?
ssl-listener?)]
[pathname path-string?]
[rsa? boolean? #t]
[asn1? boolean? #f])
void?]{
Loads the first private key from @racket[pathname] for the given
context or listener. The key goes with the certificate that identifies
the client or server. Like @racket[ssl-load-certificate-chain!], this
procedure is usually used with server contexts or listeners, seldom
with client contexts.
If @racket[rsa?] is @racket[#t] (the default), the first RSA key is
read (i.e., non-RSA keys are skipped). If @racket[asn1?] is
@racket[#t], the file is parsed as ASN1 format instead of PEM.
You can use the file @filepath{test.pem} of the @filepath{openssl}
collection for testing purposes. Since @filepath{test.pem} is public,
such a test configuration obviously provides no security.
}
@defproc[(ssl-load-suggested-certificate-authorities!
[context-or-listener (or/c ssl-client-context? ssl-server-context?
ssl-listener?)]
[pathname path-string?])
void?]{
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 @racket[ssl-load-verify-root-certificates!].
You can use the file @filepath{test.pem} of the @filepath{openssl}
collection for testing purposes where the peer identifies itself using
@filepath{test.pem}.}
@; ----------------------------------------------------------------------
@section[#:tag "peer-verif"]{Peer Verification}
@defproc[(ssl-set-verify! [clp (or/c ssl-client-context? ssl-server-context?
ssl-listener?
ssl-port?)]
[on? any/c]) void?]{
ssl-listener? ssl-port?)]
[on? any/c])
void?]{
Requires certificate verification on the peer SSL connection when
@racket[on?] is @racket[#t]. If @racket[clp] is an SSL port, then the
@ -512,8 +527,7 @@ context or listener, certification verification happens on each
subsequent connection using the context or listener.
Enabling verification also requires, at a minimum, designating trusted
certificate authorities with
@racket[ssl-load-verify-root-certificates!].
certificate authorities with @racket[ssl-load-verify-source!].
Verifying the certificate is not sufficient to prevent attacks by
active adversaries, such as
@ -523,9 +537,9 @@ attacks}. See also @racket[ssl-set-verify-hostname!].
@defproc[(ssl-try-verify! [clp (or/c ssl-client-context? ssl-server-context?
ssl-listener?
ssl-port?)]
[on? any/c]) void?]{
ssl-listener? ssl-port?)]
[on? any/c])
void?]{
Like @racket[ssl-set-verify!], but when peer certificate verification fails,
then connection continues to work. Use @racket[ssl-peer-verified?] to determine
@ -624,22 +638,3 @@ until an end-of-file.}
Converts the given byte string to a string representation, where each
byte in @racket[bstr] is converted to its two-digit hexadecimal
representation in the resulting string.}
@; ----------------------------------------------------------------------
@section{Implementation Notes}
For Windows, @racketmodname[openssl] relies on @filepath{libeay32.dll}
and @filepath{ssleay32.dll}, where the DLLs are located in the same
place as @filepath{libmzsch@nonterm{vers}.dll} (where @nonterm{vers}
is either @tt{xxxxxxx} or a mangling of Racket's version
number). The DLLs are distributed as part of Racket.
For Unix variants, @racketmodname[openssl] relies on
@filepath{libcrypto.so} and @filepath{libssl.so}, which must be
installed in a standard library location, or in a directory listed by
@envvar{LD_LIBRARY_PATH}.
For Mac OS X, @racketmodname[openssl] relies on
@filepath{libssl.dylib} and @filepath{libcrypto.dylib}, which are part
of the OS distribution for Mac OS X 10.2 and later.