From 9a07eed458186807cbf094264d8b96b9e74762c7 Mon Sep 17 00:00:00 2001 From: Ryan Culpepper Date: Sat, 24 Nov 2012 16:07:25 -0500 Subject: [PATCH] update docs --- collects/openssl/openssl.scrbl | 331 ++++++++++++++++----------------- 1 file changed, 163 insertions(+), 168 deletions(-) diff --git a/collects/openssl/openssl.scrbl b/collects/openssl/openssl.scrbl index 656fc6d2af..c7311049f9 100644 --- a/collects/openssl/openssl.scrbl +++ b/collects/openssl/openssl.scrbl @@ -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.