|set|toc2=next=cols=2,80| |1Transport Layer Security| |^ |*Transport Layer Security| (TLS), and its predecessor |*Secure Sockets Layer| (SSL), are cryptographic protocols designed to provide communication privacy over a network, in the case of HTTP between the browser (client) and the server. It also authenticates server and optionally client identity. TLS/SSL operates by establishing an encrypted communication path between the two applications, "wrapping" the entire application protocol inside the secure link, providing complete privacy for the entire transaction. In this way security-related data such as user identification and password, as well as sensitive transaction information can be protected from unauthorized access while in transit. This section is not a tutorial on TLS/SSL. It contains only information relating to WASD's use of it. See |link|SSL References| for further information on TLS/SSL technology. |note| |0TLS and SSL| The terms are used interchangably in this document to represent cryptographic communication technology. They are similar but with important differences. TLS is the more modern and considered the more secure. The term SSL is still in common usage though and retained here even if WASD (and OpenSSL) now only implements TLS. When OpenSSL(.org) considers changing its name WASD will toss out the term SSL |'_smiley.\ | |!note| |^ |table| |~ |. |image&width:208px;|./OpenSSL_logo.png| |.#= WASD implements SSL using a freely available software toolkit supported by the |*OpenSSL Project||. |!table| |^ OpenSSL licensing allows unrestricted commercial and non-commercial use. This toolkit is in use regardless of whether the WASD OpenSSL package, HP SSL for OpenVMS product, or other stand-alone OpenSSL environment is installed. It is always preferable to move to the latest support release of OpenSSL as known bugs in previous versions are progressively addressed (ignoring the issue of new bugs being introduced ;-) |note| |0TLS functionality is not supplied with the basic WASD package| In part this is due to the relative bulk of this component, in further part that the updates to each are not necessarily coincident, and also considers potential patent issues and export restrictions on some cryptography technology in some jurisdictions. |!note| |0Cryptography Software|| |^ Be aware that export/import and/or use of cryptography software, or even just providing cryptography hooks, is illegal in some parts of the world. When you re-distribute this package or even email patches/suggestions to the author or other people, please |*PAY CLOSE ATTENTION TO ANY APPLICABLE EXPORT/IMPORT LAWS||. The author of this package is not liable for any violations you make here. |0Some Thoughts From R. S. Engelschall|| |^ Ralf S. Engelschall (rse@engelschall.com) is the author of the popular Apache |/mod_ssl| package. This section is taken from the |/mod_ssl| read-me and is well-worth some consideration for this and software security issues in general. |quote| You should be very sensible when using cryptography software, because just running an SSL server |_DOES NOT| mean your system is then secure! This is for a number of reasons. The following questions illustrate some of the problems. |bullet#| |& SSL itself may not be secure. People think it is, do you? |& Does this code implement SSL correctly? |& Have the authors of the various components put in back doors? |& Does the code take appropriate measures to keep private keys private? To what extent is your cooperation in this process required? |& Is your system physically secure? |& Is your system appropriately secured from intrusion over the network? |& Whom do you trust? Do you understand the trust relationship involved in SSL certificates? Do your system administrators? |& Are your keys, and keys you trust, generated careful[ly] enough to avoid reverse engineering of the private keys? |& How do you obtain certificates, keys, and the like, securely? |& Can you trust your users to safeguard their private keys? |& Can you trust your browser to safeguard its generated private key? |!bullet| If you can't answer these questions to your personal satisfaction, then you usually have a problem. Even if you can, you may still |_NOT| be secure. Don't blame the authors if it all goes horribly wrong. Use it at your own risk! |!quote+| |2Let's Encrypt| |^ Have (or want) a TLS/SSL secured site? |^ Using self-signed or commercial server certificate(s)? |^ |*Let's Encrypt| makes it possible to obtain and maintain browser-trusted certificates, simply, automatically and |*at no cost||. |^ See |_WASD Certificate Management Environment| (wuCME) on the WASD download page at |%https://wasd.vsm.com.au/wasd/#wucme|\ https://wasd.vsm.com.au/wasd/| |2TLS/SSL Functionality Sources| |^ Secure Sockets Layer functionality is easily integrated into WASD and is available from one (or more) of the following sources. See |\|link|(hd_ssl_quick_start)| for the basics of installing WASD SSL and |\|link|(hd_ssl_config)| for configuration of various aspects. |note><| |0All OpenSSL 1.0.2 and earlier| are considered obsolete, deprecated and unsupported |!note| |number| |item| The |*VSI SSL111 for OpenVMS| product |^ This is provided from the directory SYS$COMMON:|link%|/sys$common/ssl111/*.*|[SSL111]|| containing shared libraries, executables and templates for certificate management, etc. If this product is installed and started the WASD installation and update procedures should detect it and provide the option of compiling and/or linking WASD against its shareable libraries. |item| As a separate, easily integrated |*WASD OpenSSL package||, with OpenSSL object libraries, OpenSSL utility object modules for building executables and WASD support files. Currently it is based on the OpenSSL v1.1.1 code stream. The package requires no compilation, only linking, and is available for Alpha and Itanium for VMS version 7.0 up to current. |^ WASD OpenSSL installation creates an OpenSSL directory in the source WASD_ROOT:[SRC|link%|/wasd_root/src/*.*|.OPENSSL-n_n_n]| \ (look for it here) containing the OpenSSL copyright notice, object libraries, object modules for building executables, example certificates, and some other support files and documentation. |item| Using a locally compiled and installed |*OpenSSL toolkit||. |^ The OpenSSL v1.1.1 code stream is supported. WASD requires a 32 bit OpenSSL build (the default). |^ To change linkage use step 2 described in |\|link|(hd_ssl_quick_start)|| selecting the alternate toolkit build. |^ OpenSSL v1.1.1 uses the naming schema OSSL$|...| for logical and file names. It also provides object libraries for a static linked executable, as well as shareable images, for the two main APIs (SSL and crypto). In common with the VSI SSL111 product, the shareable images must be installed to be used with the WASD server privileged executable. The WASD STARTUP.COM procedure will undertake this when directed (see immediately below). |^ There is one other consideration. For a privileged executable to activate a shareable image, not only must the image be installed but any associated logical names must be defined in executive (or kernel) mode. When executing the OpenSSL v1.1.1 startup procedure P1 must be "|=/SYSTEM/EXECUTIVE||" as in the following example: |code| $ @SYS$COMMON:[OPENSSL.SYS$STARTUP]OPENSSL_STARTUP0101.COM "/SYSTEM/EXECUTIVE" $ @WASD_ROOT:[STARTUP]STARTUP WASD_OSSL=1 |!code| |!number| |2WASD SSL Quick-Start| |^ SSL functionality can be installed with a new package, or with an update, or it can be added to an existing non-SSL enabled site. The following steps give a quick outline for support of SSL. |number| |item| If using the VSI SSL111 product or an already installed OpenSSL toolkit go directly to step 2. To install the WASD OpenSSL package the ZIP archive needs to be restored. |bullet| |item| The ZIP archive will contain brief installation instructions. Use the following command to read this and any other information provided. |code| $ UNZIP -z device:[dir]archive.ZIP |!code| |item| |_Either| UNZIP the WASD OpenSSL package into a new installation |code| $ SET DEFAULT [.WASD_ROOT] $ UNZIP device:[dir]archive.ZIP |!code| |item| |_OR| into an existing installation |code| $ SET DEFAULT WASD_ROOT:[000000] $ UNZIP device:[dir]archive.ZIP |!code| |!bullet| |item| It is then necessary to build the (server and Open)SSL executables. |bullet| |item| If during an original INSTALL or subsequent UPDATE of the entire package the procedures detect a suitable SSL toolkit and prompt the user whether an SSL enabled server should be built. |item| To to add SSL functionality to an existing but non-SSL site just the SSL components can be built using the following procedure. |code| $ @WASD_ROOT:[INSTALL]UPDATE SSL |!code| |!bullet| |item| Once linked the UPDATE.COM procedure will prompt for permission to execute the demonstration/check procedure. |^ It is also possible to check the SSL package at any other time using the server demonstration procedure. It is necessary to specify that it is to use the SSL executable. Follow the displayed instructions. |code| $ @WASD_ROOT:[INSTALL]DEMO.COM SSL |!code| |item| Modification of server startup procedures should not be necessary. If an SSL image is detected during startup it will be used in preference to the standard image. |item| Modify the WASD_CONFIG_SERVICE configuration file to specify an SSL service. For example the following adds a generic SSL service on port 443. |code| [[https://*:443]] |!code| |item| Shutdown the server completely, then restart. |code| $ HTTPD /DO=EXIT $ @WASD_ROOT:[STARTUP]STARTUP |!code| |item| To check the functionality (on default ports) access the server via |simple| |item| Standard HTTP |code| http://the.example.com/ |!code| |item| SSL HTTP |code| https://the.example.com/ |!code| |!simple| |item| Once the server has been proved functional with the example certificate it is recommended that a server-specific certificate be created using the tools described in |link|Server Certificate| and |link|Certificate Management||. |!number| |2OPENSSL.EXE Application| |^ The OPENSSL.EXE application is a command line tool for using the various cryptography functions of OpenSSL's crypto library from the shell. It is described being used several times in this section of the documentation. Refer to the OpenSSL Man page for descriptions of the various commands and their syntax. |simple#| |& |%https://www.openssl.org/docs/manmaster/man1/openssl.html| |& |%https://wiki.openssl.org/index.php/Command_Line_Utilities| |!simple| |^ It is commonly used as a |/foreign verb| on VMS systems and assigned during SYLOGIN.COM or LOGIN.COM and depends on the distribution and version in use. For example: |simple#| |& $ @SSL111$COM:SSL111$UTILS.COM |& $ @OSSL$INSTROOT:[SYS$STARTUP]OPENSSL_UTILS0101.COM |!simple| |^ A simple addition to SYLOGIN.COM or LOGIN.COM for WASD-specific OpenSSL kits to assign the OPENSSL verb is: |code| $ @WASD_ROOT:[EXAMPLE]WASDVERBS.COM SSL |!code| |2SSL Configuration| |^ The example server startup procedure already contains support for the SSL executable. If this has been used as the basis for startup then an SSL executable will be started automatically, rather than the standard executable. The SSL executable supports both standard HTTP services (ports) and HTTPS services (ports). These must be configured using the [service] parameter. SSL services are distinguished by specifying "https:" in the parameter. The default port for an SSL service is 443. |^ WASD can configure services using the WASD_CONFIG_GLOBAL [SSL..] directives, the per-service WASD_CONFIG_SERVICE [ServiceSSL..] directives, or the /SSL= qualifier. Configuration precedence is WASD_CONFIG_SERVICE, /SSL= and finally WASD_CONFIG_GLOBAL. |3WASD_CONFIG_SERVICE| |^ SSL service configuration using the WASD_CONFIG_SERVICE configuration is slightly simpler, with a specific configuration directive for each aspect. (see |link%|../config/##Service Configuration++of++WASD Configuration||). This example illustrates configuring the same services as used in the previous section. |code| [[http://alpha.example.com:80]] [[https://alpha.example.com:443]] [ServiceSSLversion] TLSvALL [ServiceSSLcert] WASD_ROOT:[local]alpha.pem [[https://beta.example.com:443]] [ServiceSSLversion] SSLv3 [ServiceSSLcert] WASD_ROOT:[local]beta.pem |!code| |3TLS/SSL Versions| |9SSL Versions| |^ As WASD uses the OpenSSL package in one distribution or another it largely supports all of the capability of that underlying package. The obsolete SSLv2, and the deprecated SSLv3 are no longer accepted by default. WASD default comprise the TLS family of protocols, at the time of writing, |*TLSv1, TLSv1.1, TLSv1.2 and TLSv1.3||. |^ Some older clients employing SSLv3 may fail. Symptoms are dropped connection establishment and WATCH [x]SSL variously showing "SSL routines SSL|/n||_GET_RECORD wrong version number", "SSL routines SSL|/n||_GET_CLIENT_HELLO unknown protocol", possibly others. It is generally considered SSL best-practice not to have SSLv3 enabled but if required may be supported by configuring WASD_CONFIG_GLOBAL [SSLversion] with "SSLv3,TLSvALL", the per-service WASD_CONFIG_SERVICE equivalent, or using the /SSL=(SSLv3,TLSvALL) command line parameter during server startup. |0TLS Version 1.3|| |^ TLSv1.3 perhaps should have been designated TLSv2.0 and not be considered as an incremental improvement over earlier versions of TLS but a significant upgrade! |simple| |& |%https://wiki.openssl.org/index.php/TLS1.3| |!simple| |^ TLSv1.3 can be tested for as demonstrated at |link|test TLS Version 1.3||. |3SSL Ciphers| |^ Ciphers are the algorithms, designed and implemented on mathematical computations, that render the readable plaintext into unreadable ciphertext. Ciphers tend to be available in suites (or families) where variants, usually based on key size and therefore resistence to decryption without a known key, that browsers and otheragents negotiate on and accept when setting up a secure (encrypted) network transports with servers. |^ Cipher selection is important to the overall security of the supported environment as well as the range of clients and servers that can establish communication due to shared cipher suites. Including only more recent (and technically secure) ciphers can preclude older clients from establishing secure connection, and including older (and perhaps more susceptible to modern attack) ciphers increases site vunerability. Some environments, for example HTTP/2, are quite prescriptive regarding the secure connection, to the point of blacklisting protocol versions and cipher suites no longer considered secure enough. |^ Fortunately a number of sites provide cipher guidelines based on requirements. The Mozilla Developer Network provides these amongst other useful information on security and server side TLS. |^+ |%https://wiki.mozilla.org/Security/Server_Side_TLS| |^ WASD has a default (built-in) functional cipher list that is general in application and relevant to when it was compiled. This in particular and site cipher lists in general, should be reviewed from time to time as opinions and requirements do change. |^ Many agents (browsers) require the elliptic curve ciphers provided by Forward Secrecy elements (|link|Forward Secrecy||) to negotiate later TLS versions. |9.SSL Options| |9.TLS/SSL Options| |9.OpenSSL Options| |3.(Open)SSL Options| |^ The OpenSSL package provides for various options to be flagged against an TLS/SSL service. WASD sets the (OpenSSL) default options and then allows these to be overwitten/set/reset using hexadecimal values representing bit patterns. OpenSSL defaults are suitable for most sites. |^ The SSL options directives in global and per-service configuration, and the OPTIONS= keyword for the /SSL= qualifier, accept |simple#| |& 0x|/XX| - overwrite the options field |& +0x|/XX| - set (logical OR) the specified bit(s) |& -0x|/XX| - reset (logical AND) the specified bit(s) |!bullet| |^ Alternatively, the following OpenSSL option mnemonics can be used with a leading "+" to enable, or "-" to disable |simple#| |& OP_ALL |& OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION |& OP_CIPHER_SERVER_PREFERENCE |& OP_LEGACY_SERVER_CONNECT |& OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |& OP_NO_TICKET |& OP_SINGLE_DH_USE |& OP_TLS_ROLLBACK_BUG |!simple| |3Forward Secrecy| |^ Forward secrecy, sometimes known as perfect forward secrecy (PFS), is a property of key-agreement protocols ensuring that a session key derived from a set of long-term keys cannot be compromised if one of the long-term keys is compromised in the future. |^+ |%http://en.wikipedia.org/wiki/Forward_secrecy| |^ OpenSSL supports forward secrecy using Diffie-Hellman key exchange with elliptic curve cryptography and this relies on generating emphemeral keys based on unique, safe prime numbers. These are expensive to generate and so this is done infrequently, often during software build or installation. In the case of WASD, to maximise flexibility, these numbers are stored in external PEM-format files, by default located in the WASD_ROOT:[LOCAL] directory. These files are only briefly accessed during server startup SSL initialisation and the content later used during network connection SSL negotiation to generate the required ephemeral keys. |^ PFS requires a small number of elements working in concert |bullet#| |& Ephemeral key generation |& Selection and ordering of server ciphers |& Ensuring the server determines the cipher used (+OP_CIPHER_SERVER_PREFERENCE) |!bullet| |^ The detail is described in these references |simple#| |& |%https://community.qualys.com/blogs/securitylabs/2013/06/25/\ ssl-labs-deploying-forward-secrecy| |& |%https://community.qualys.com/blogs/securitylabs/2013/08/05/\ configuring-apache-nginx-and-openssl-for-forward-secrecy| |!simple| |note><| Ephemeral keys are supported beginning with WASD v10.4.1. |!note| |^ Executing the WASD OpenSSL procedure |code| $ @CREATE_EPHEMERAL_DH_PARAM |!code| will generate site-unique files containing 512, 1024 and 2048 bit primes, and optionally copy those files to the WASD_ROOT:[LOCAL] directory. The [.CERT] directory contains files that could be used but unique, locally generated primes are preferable. |^ Alternatively, generated directly at the command-line using the OpenSSL |/dhparam| utility, as in these examples; |code| $ openssl dhparam -out dh_param_512.pem 512 $ openssl dhparam -out dh_param_1024.pem 1024 $ openssl dhparam -out dh_param_2048.pem 2048 |!code| |note><| Key generation can take some considerable time! |!note| The file(s) must be located in the WASD_ROOT:[LOCAL] directory and the file names use the format DH_PARAM_|/number-of-bits||.PEM |^ Alternatively, files containing emphemeral keys generated freshly with each release, may be copied from the WASD OpenSSL package using |code| $ COPY WASD_ROOT:[SRC.OPENSSL-n_n_n.WASD.CERT]DH_PARAM_*.PEM WASD_ROOT:[LOCAL] |!code| |3Session Resumption| |^ When a TLS/SSL connection is initiated an expensive handshake (in terms of time and compute) is required to establish the cryptographic and other elements of the connection. Mitigation of this expense is undertaken by allowing the resumption of a previous session (abbreviating the handshake exchanges) using connection state stored either at the server or at the client. |bullet| |item| |*Session Ticket|| |^ This TLS extension provides the connection state to the client, encrypted with keys available only to the server. The client stores the (encrypted) state and when (re-)connecting to the server provides that ticket in the initial part of the handshake. The server decrypts the ticket and if valid expedites the connection by resuming the previously negotiated session. This is the more modern, almost universally supported mechanism and is generally enabled by default. |^ Session tickets introduce a potential vulnerability to TLS security, in particular to the benefits of Forward Secrecy (PFS). If the ticket can be compromised, through theft of the keys or brute-force decryption attack, the entire session becomes vulnerable to attack. It is therefore advised to periodically rotate (change) the keys used by the server to encrypt the tickets. WASD does this every (RFC recommended) 24 hours, at midnight (local time). |^ Where a site is provided by multiple servers and connections distributed between these, session resumption using tickets relies on each server using the same keys. The current keys must be distributed to each server (using a secure mechanism) and this performed every time the keys are rotated. WASD uses the DLM to perform this for multiple per-node and cluster-wide instances as applicable. |item| |*Session ID| |^ In a full handshake the server sends a Session ID (unique, non-repeating value) as part of the handshake. On a subsequent connection the client can pass this session ID back to the server when connecting. To support session resumption via session IDs the server must maintain a cache that maps past session IDs to those sessions' states. The cache has limited capacity and is expensive for the server to maintain. If the session ID is still available in the cache the session can be resumed. This is the original session resumption mechanism. |^ Where a single WASD instance is involved the session cache is implemented in-memory. With multiple instances on a single node it is provided across those instances using a shared global section. The cacpacity of this shared cache is determined by the WASD_CONFIG_GLOBAL directives [SSLinstanceCacheMax] and [SSLinstanceCacheSize] directives. There is no cluster-wide session cache. When multiple instances are in use the shared session cache is enabled by default. Session ID caching may be globally disabled by setting [SSLsessionCacheMax] to -1. |!bullet| |^ With Session Tickets being the more modern, flexible and efficient solution to session resumption (and being available cluster-wide) it is recommended that WASD sites disable Session ID caching. |^ The default maximum period for session reuse is five minutes. This may be set globally using the [SSLsessionLifetime] directive or on a per-service basis using [ServiceSSLsessionLifetime]. |^ To some extent, the relatively long-lived connections and lower concurrency with HTTP/2 means the importance of session resumption in improving request latency and connection overhead is reduced. |3Strict Transport Security| |^ HTTP Strict Transport Security (HSTS) is a security policy mechanism which helps protect sites against protocol downgrade attack and cookie hijacking. It allows web servers to declare that browsers and other complying agents should only interact using secure (TLS) HTTP connections and never via clear-text HTTP. HSTS is an IETF standard specified in RFC 6797. |^ When global configuration directive [SSLstrictTransSec] is non-zero, or per-service configuration directive [ServiceSSLstrictTransSec] is non-zero, or a path is |/SET response=sts=||, TLS/SSL HTTP responses include a "Strict-Transport-Security: max-age=|/seconds||" header field. Conforming agents note this period and refuse to communicate with the site via clear-text HTTP for the period represented by the integer number of seconds specified. |3SSL Server Certificate| |^ The server certificate is used by the browser to authenticate the server against the server certificate Certificate Authority (CA), in making a secure connection, and in establishing a trust relationship between the browser and server. By default this is located using the WASD_CONFIG_GLOBAL [SSLcert] or WASD_CONFIG_SERVICE [ServiceSSLcert] configuration directive, the WASD_CONFIG_SSL_CERT logical name, or using the /SSL= command-line qualifier, however if required. Each SSL service can have an individual certificate configured as in the example above. |3SSL Private Key| |^ The |/private key| is used to validate and enable the server certificate. A private key is enabled using a |/secret||, a password. It is common practice to embed this (encrypted) password within the private key data. This private key can be appended to the server certificate file, or it can be supplied separately. If provided separately it can be located using the WASD_CONFIG_GLOBAL [SSLkey] or WASD_CONFIG_SERVICE [ServiceSSLkey] configuration directive, tor using the WASD_CONFIG_SSL_KEY logical. When the password is embedded in the private key information it becomes vulnerable to being stolen as an enabled key. For this reason it is possible to provide the password separately and manually. |^ If the password key is not found with the key during startup the server will request that it be entered at the command-line. This request is made via the HTTPDMON "STATUS:" line (see |link%|../config/##OPCOM Logging++of++WASD Configuration||), and if any OPCOM category is enabled via an operator message. If the private key password is not available with the key it is recommended that OPCOM be configured, enabled and monitored at all times. |^ When a private key password is requested by the server it is supplied using the /DO=SSL=KEY=PASSWORD directive (|link|HTTPd Command Line||). This must be used at the command line on the same system as the server is executing. The server then prompts for the password. |code| Enter private key password []: |!code| The password is not echoed. When entered the password is securely supplied to the server and startup progresses. An incorrect password will be reprompted for twice (i.e. up to three attempts are allowed) before the startup continues with the particular service not configured and unavailable. Entering a password consisting of all spaces will cause the server to abort the full startup and exit from the system. |3SSL Virtual Services| |^ Multiple virtual SSL services (https:) sharing the same or individual certificates (and other characteristics) can essentially be configured against any host name (unique IP address or host name alias) and/or port in the same way as standard services (http:). |^ WASD SSL implements |*Server Name Indication| (SNI), an extension to the TLS protocol that indicates what hostname the client is attempting to connect to at the start of the handshaking process. This allows a server to present multiple certificates on the same IP address and port number and hence allows multiple secure (HTTPS) websites (or any other Service over TLS) to be served off the same IP address without requiring all those sites to use the same certificate. |^ When the client presents an SNI server name during SSL connection establishment, WASD searches the list of services it is offering for an SSL service (the first hit) operating with a name matching the SNI server name. If matched, the SSL context (certificate, etc.) of that service is used to establish the connection. If not matched, the service the TCP/IP connection originally arrived at is used. |3SSL Access Control| |^ When authorization is in place (|link|Authentication and Authorization||) access to username/password controlled data/functionality benefits enormously from the privacy of an authorization environment inherently secured via the encrypted communications of SSL. In addition there is the possibility of authentication via client X.509 certification (|link|Authorization Using X.509 Certification)||). SSL may be used as part of the site's access control policy, as whole-of-site, see |link|Authentication Policy||, or on a per-path basis (see |link%|../config/##Request Processing Configuration++of++WASD Configuration||). |3Authorization Using X.509 Certification| |^ The server access control functionality (authentication and authorization) allows the use of |/public key infrastructure| (PKI) X.509 v3 client certificates for establishing identity and based on that apply authorization constraints. See |link|Authentication and Authorization| for general information on WASD authorization and |link|Authorization Configuration File| for configuring a X509 realm. |link|Transport Layer Security| provides introductory references on public-key cryptography and PKI. |^ A client certificate is stored by the browser. During an SSL transaction the server can request that such a certificate be provided. For the initial instance of such a request the browser activates a dialog requesting the user select one of any certificates it has installed. If selected it is transmitted securely to the server which will usually (though optionally not) authenticate its Certificate Authority to establish its integrity. If accepted it can then be used as an authenticated identity. This obviates the use of username/password dialogs. |note| |0Important| Neither username/password nor certificate-based authentication addresses security issues related to access to individual machines and stored certificates, or to password confidentiality. Public-key cryptography only verifies that a private key used to sign some data corresponds to the public key in a certificate. It is a user responsibility to protect a machine's physical security and to keep private-key passwords secret. |!note| |^ The initial negotiation and verification of a client certificate is a relatively resource intensive process. Once established however, OpenSSL sessions are usually either stored in a cache or stored encrypted withing the client, reducing subsequent request overheads significantly. Each session has a specified expiry period after which the client is forced to negotiate a new session. This period is adjustable using the "[LT:integer]" and "[TO:integer]" directives described below. |3X.509 Certificate Renegotiation| |^ An X.509 client certificate is requested at either TLS/SSL connection establishment (WASD_CONFIG_GLOBAL [SSLverifyPeer], WASD_CONFIG_SERVICE [ServiceSSLverifyPeer]) or once the request has been made and assessed against authorisation rules. If an X509 realm controls access to the resources then the TLS/SSL connection is queried for an X.509 client certificate to authenticate the client and authorise the access. |^ This is performed via a TLS/SSL renegotiation and for this the connection must have been cleared of request data. In the case of a HEAD, GET, OPTIONS, etc. request, this already has implicitly occurred by there being no request body. For POST, PROPFIND, PUT, etc. requests, the client most likely already will be transmitting the request body. This (|/application data||) must be absorbed before the client certificate renegotiation can be performed. |^ In avoiding disruption to the current request, any request body must be buffered (in full, based on the content length specified in the header) before issuing the renegotiation. This consumes memory and potentially large quantities. The default maximum buffer space is 1MB. The maximum request body size and hence maximum memory accomodated can be configured using the per-service WASD_CONFIG_SERVICE [ServiceSSLverifyDataMax] directive, or the global WASD_CONFIG_GLOBAL configuration directive [SSLverifyDataMax]. |^ Where a request with a body exceeds the maximum allowed buffer space the authorisation fails. This can be observed using WATCH. Where very large files are being sent the only solution is to first authenticate with a request without a body (e.g. using OPTIONS) then using the persistent connection and associated X.509 authentication perform the PUT or POST. |3Features| |^ WASD provides a range of capabilities when using X.509 client certificates. |bullet| |item| |*By Service |-| | all SSL connections to such a service will be requested to supply a client certificate during the initial SSL handshake. This is more efficient than requesting later in the transaction, as happens with per-resource authorization. A client cannot connect successfully to this type of service without supplying an acceptable certificate. |item| |*By Resource |-| | using authorization rules in the WASD_CONFIG_AUTH file specifying a path against an [X509] realm causes the server to suspend request processing and renegotiate with the client to supply a certificate. If a suitable certificate is supplied the request authorization continues with normal processing. This obviously incurs an additional network transaction. |item| |*Optional access control |-| | once an acceptable certificate is supplied it can be subject to further access control by matching against its contents. The |/Issuer| (CA) and the |/Subject| (client) |/Distinguished Name| (DN) has various components including the name of the organization providing the certificate (e.g. "VeriSign", "Thawte"), location, common name, email address, etc. Those certificates matching or not matching the parameters are allowed or denied access. |item| |*Certificate verification |-| | by default supplied certificates have their CA verified by comparing to a list of recognised CA certificates stored in a server configuration file. If the CA component of the client certificate cannot be verified the connection is terminated before the HTTP request can begin. Although this is obviously required behaviour for authentication there may be other circumstances where verification is not required, a certificate content display service for instance. WASD optionally allows non-verified certificates to be used on a per-resource basis. |item| |*."Fingerprint" REMOTE_USER |-| | when a certificate is accepted by the server it generates a unique |/fingerprint| of the certificate. By default, this 32 digit hexadecimal number is used by the server as an |/effective username||, one that would normally be supplied via a username/password dialog (as an alternative see the section immediately below). This effective username becomes that available via the CGI variable REMOTE_USER. Although a 32 digit number is not particularly site-administrator friendly it is a |_unique| representation (MD5 digest) of the individual certificate and can be used in WASD_CONFIG_AUTH access-restriction directives and included in group lists and databases for full WASD authorization control. |item| |*CN/DN record REMOTE_USER |-| | provides an alternative to using a "fingerprint" REMOTE_USER. Using the [RU:/|/record||=] conditional (see below) is becomes possible to specify that the remote-user string be obtained from the specified record of the client certificate subject field. Note that there is a (fairly generous) size limitation on the user name and that any white-space in such a record is converted to underscores. Although any record can be used the more obvious candidates are /O=, /OU=, /CN=, /S=, /UID= and /EMAIL=. Note that (even with the default CA verfication) the certificate CAs that this is possible against should be further constrained through the use of a [IS:/|/record||=|/string||] conditional (see example below). |item| |*Subject Alternative Name REMOTE_USER |-| | a common X509 V3 extension for providing identifying data in a certificate, can also be used to derive the remote user string. |item| |*X509 extension REMOTE_USER |-| | the content of any other extension field suitably filtered. |!bullet| |3Subject Alternative Name and Other Extensions| |^ The basic syntax for this field is the full extension name, and the short-hand equivalent. |code| [X509] /VMS/* r+w,param="[ru:X509v3_subject_Alternative_Name]" /VMS/* r+w,param="[ru:X509v3_SAN]" |!code| |^ The Subject Alternative Name (SAN) extension (in common with many others) may contain multiple data elements, each with a leading name, a colon, and a (if multi line) carriage-control terminated value. WASD parses these into unqiue fields using keywords fixed in function SesolaCertKeyword() and the site configurable logical name WASD_X509_EXTENSION_KEYWORDS value. To select one of these fields, for example the common (Microsoft) user principal name (UPN), append the required field name to the extension name as shown in the following example (includes "shorthand" equivalents, along with the underscore and equate variants). Note that the identifying name match is not case sensitive. |code| [X509] /VMS/* r+w,param="[ru:X509V3_Subject_Alternative_Name_UserPrincipalName]" /VMS/* r+w,param="[ru:X509V3_Subject_Alternative_Name=UserPrincipalName]" /VMS/* r+w,param="[ru:X509v3_SAN_UPN]" /VMS/* r+w,param="[ru:X509v3_SAN=UPN]" /VMS/* r+w,param="[ru:X509V3_Subject_Alternative_Name_rfc822Name]" /VMS/* r+w,param="[ru:X509V3_Subject_Alternative_Name=rfc822Name]" /VMS/* r+w,param="[ru:X509v3_SAN_822]" /VMS/* r+w,param="[ru:X509v3_SAN=822]" |!code| |^ Object Identifiers (OIDs) may be used for either record and field name (if an unknown otherName) by prefixing with "OID_". For example, the SAN may be alternatively selected, and the (Microsoft) UPN, as in the following examples. |code| /VMS/* r+w,param="[ru:OID_2_5_29_17]" /VMS/* r+w,param="[ru:OID_2_5_29_17_UPN]" /VMS/* r+w,param="[ru:OID_2_5_29_17=UPN]" /VMS/* r+w,param="[ru:X509v3_SAN_OID_1_3_6_1_20_2_3]" /VMS/* r+w,param="[ru:X509v3_SAN_OID=1_3_6_1_20_2_3]" |!code| |0Extension Visibility|| |^ X509 certificate extensions are in general visible from WATCH and accessible via CGI variables (when enabled using SET |/SSLCGI=apache_mod_ssl_extens| and |/SSLCGI=apache_mod_ssl_client| path mappings). The identifying names derived from X509 extensions are built of the alphanumerics in the element names. Non-alphanumerics (e.g. spaces) have underscores substituted. Multiple underscores are compressed into singles. Where elements have identical names the first multiple has TWO underscores and the digit two appended, the second mutiple, two underscores and three appended, etc. |3X509 Configuration| |^ Of course, the WASD OpenSSL component must be installed and in use to apply client X.509 certificate authorization. There is general server setup, then per-service and per-resource configuration. |0General Setup|| |^ Client certificate authorization has reasonable defaults. If some aspect requires site refinement the WASD_CONFIG_GLOBAL [SSL..] directives (see |link%|../config/##|WASD Configuration||) or command-line /SSL= qualifier parameters can provide per-server defaults. |bullet#| |& (CACHE=integer) sets the session size (128 entries by default) |& (CAFILE=file-name) sets the location of the CA verification store file (also can be set via WASD_CONFIG_SSL_CAFILE logical). |& (TIMEOUT=integer) sets the session expiry period in minutes (5 by default) |& (VERIFY=integer) sets the depth to which client certificate CAs are verified (default is 10) |!bullet| |^ The location of the CA verification file can also be determined using the logical name WASD_CONFIG_SSL_CAFILE. The order of precedence for using these specifications is |number#| |& per-service configuration using WASD_CONFIG_SERVICE or WASD_CONFIG_GLOBAL |& per-server using /SSL=CAFILE=filename |& per-server using WASD_CONFIG_SSL_CAFILE |!number| |0By Service|| |^ The WASD_CONFIG_SERVICE directive is provided for per-service CA file specification, if necessary allowing different services to accept a different mix of CAs. |code| [[https://the.example.com:443]] [ServiceSSLVerifyPeer] enabled [ServiceSSLVerifyPeerCAfile] WASD_ROOT:[LOCAL]CA_THE_HOST_NAME.TXT |!code| |0By Resource|| |^ Client certificate authorization is probably most usefully applied on a per-resource (per-request-path) basis using WASD_CONFIG_AUTH configuration file rules. Of course, per-resource control also applies to services that always require a client certificate (the only difference is the certificate has already been negotiated for during the initial connection handshake). The reserved realm name "X509" activates client certificate authentication when a rule belonging to that realm is triggered. The following example shows such a rule providing read access to those possessing any verified certificate. |code| [X509] /path/requiring/cert/* r |!code| |^ Optional directives may be supplied to the X.509 authenticator controlling what mode the certificate is accepted in, as well a further access-restriction rules on specifically which certificates may or may not be accepted for authorization. Such directives are passed via the "param=" mechanism. The following real-life example shows a script path requiring a mandatory certificate, but not necessarily having the CA verified. This would allow a certificate display service to be established, the "[to:EXPIRED]" directive forcing the client to explicitly select a certificate with each access. |code| [X509] /cgi-bin/client_cert_details r,param="[vf:OPTIONAL][to:EXPIRED]" |!code| |^ A number of such directives are available controlling some aspects of the certificate negotiation and verification. The "[LT:integer]" directive causes a verified certificate selection to continue to be valid for the specified period as long as requests continue during that period (lifetime is reset with each access). |bullet#| |& [DP:integer] verify certificate CA chain to this depth (default 10) |& [LT:integer] verified certificate lifetime in minutes (disabled by default) |& [RU:/record=] derive the remote-user name from the specified certificate subject field DN record |& [TO:integer] session cache entry timeout in minutes (default 5) |& [TO:EXPIRED] session cache entry is forced to expire (initating renegotiation) |& [VF:NONE] no certificate is required (any existing is cancelled) |& [VF:OPTIONAL] certificate is required, CA verification is not required |& [VF:REQUIRED] the certificate must pass CA verification (the default) |!bullet| |^ Optional "param=" passed conditionals may also be used to provide additional filtering on which certificates may or may not be used against the particular path. This is based on pattern matching against client certificate components. |bullet#| |& [CI:string] transaction cipher |& [IS:/record=string] specified Issuer (CA) DN record only |& [IS:string] entire Issuer (CA) DN |& [KS:integer] minimum key size |& [SU:/record=string] specified Subject (client) DN record only |& [SU:string] entire Subject (client) DN |!bullet| |^ These functions can be used in a similar fashion to mapping rule conditionals (see |link%|../config/##Conditional Configuration++of++WASD Configuration||). This includes the logical ORing, ANDing and negating of conditionals. Asterisk wildcards match any zero or more characters, percent characters any single character. Matching is case-insensitive. |^ Note that the "IS:" and "SU:" conditionals each have a |/specific-record| and an |/entire-field| mode. If the conditional string begins with a slash then it is considered to be a match against a specified record contents within the field. If it begins with a wildcard then it is matched against the entire field contents. Certificate DN records recognised by WASD, |simple#| |& |*/C=| countryName |& |*/ST=| stateOrProvinceName |& |*/SP=| stateOrProvinceName |& |*/L=| localityName |& |*/O=| organizationName |& |*/OU=| organizationalUnitName |& |*/CN=| commonName |& |*/T=| title |& |*/I=| initials |& |*/G=| givenName |& |*/S=| surname |& |*/D=| description |& |*/UID=| uniqueIdentifier |& |*/Email=| pkcs9_emailAddress |!simple| |^ The following (fairly contrived) examples provide an illustration of the basics of X509 conditionals. When matching against Issuer and Subject DNs some knowlege of their contents and structure is required (see |link|Transport Layer security| for some basic resources). |code| [X509] # only give "VeriSign"ed ones access /controlled/path1/* r+w,param="[IS:/O=VeriSign\\ Inc.]" # only give non-"VeriSign"ed ones access /controlled/path2/* r+w,param="[!IS:/O=VeriSign\\ Inc.]" # only allow 128 bit keys using RC4-MD5 access /controlled/path3/* r+w,param="[KS:128][CI:RC4-MD5]" # only give a "Thawte"-signed client based in Australia # with the following email address access /controlled/path4/* r+w,param="\\ [IS:*/O=Thawte\\ Consulting\\ cc/*]\\ [SU:*/C=AU/*/Email=mark.daniel@wasd.vsm.com.au*]" # use the subject DN common-name record as the remote-user name # furthermore, restrict the CA's allowed to be used this way /VMS/* r+w,param="[RU:/CN=][IS:/O=WASD\\ CA\\ Cert]" |!code| |^ Of course, access control via group membership is also available. The |/effective username| for the list is the 32 digit fingerprint of the client certificate (shown as REMOTE_USER IN the first example of |link|X.509 Authorization CGI Variables||), or the Subject DN record as specified using the [RU:/|/record||=] directive. This may be entered into simple lists as part of a group of which membership then controls access to the resource. The following examples show the contents of simple list files containing the X.509 fingerprints, derived remote-user names, and the required WASD_CONFIG_AUTH realm entries. |code| # FINGERPRINTS.$HTL # (a file of X.509 fingerprints for access to "/path/requiring/cert/") 106C8342890A1703AAA517317B145BF7 mark.daniel@wasd.vsm.com.au 6ADA07108C20338ADDC3613D6D8B159D just.another@where.ever.com # CERT_CN.$HTL # (a file of X.509 remote-user names derived using [RU:/CN=] Mark_Daniel mark.daniel@wasd.vsm.com.au Just_Another just.another@where.ever.com [X509;FINGERPRINTS=list] /path/requiring/cert/* r+w [X509;CERT_CN=list] /path/requiring/cn/* r+w |!code| |^ In a similar fashion the effective username can be placed in an access restriction list. The following configuration would only allow the user of the certificate access to the specified resources. Other verified certificate holders would be denied access. |code| [X509] /httpd/-/admin/* ~106C8342890A1703AAA517317B145BF7,r+w /wasd_root/local/* ~106C8342890A1703AAA517317B145BF7,r+w /other/path/* ~Mark_Daniel,r+w,param="[ru:/cn=]" /yet/another/path/* ~Just_Another,r+w,param="[ru:/cn=]" |!code| |3Certificate Authority Verification File| |^ For the CA certificate component of the client certificate to be verified as being what it claims to be (and thus establishing the integrity of the client certificate) a list of such certificates must be provided for comparison purposes. For WASD this list is contained in a single, plain-text file variously specified using either the WASD_CONFIG_SSL_CAFILE logical or per-service "[ServiceSSLclientCAfile]" directives, or the global [SSLverifyPeerCAFile] directive. |^ Copies of CA certificates are available for such purposes. The PEM copies (base-64 encoded versions of the binary certificate) can be placed into this file using any desired text editor. Comments may be inserted by prefixing with the "#" character. For WASD this would be best stored in the WASD_ROOT:[LOCAL] directory, or site equivalent. |^ An example of how such a file appears is provided below (bulk of the file has been 8< snipped 8< for bevity). |code| ## ## Bundle of CA Root Certificates ## ## Certificate data from Mozilla as of: Wed Jan 18 04:12:05 2017 GMT ## ## This is a bundle of X.509 certificates of public Certificate Authorities ## (CA). These were automatically extracted from Mozilla's root certificates ## file (certdata.txt). This file can be found in the mozilla source tree: ## https://hg.mozilla.org/releases/mozilla-release/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt ## ## It contains the certificates in PEM format and therefore ## can be directly used with curl / libcurl / php_curl, or with ## an Apache+mod_ssl webserver for SSL client authentication. ## Just configure this file as the SSLCACertificateFile. ## ## Conversion done with mk-ca-bundle.pl version 1.27. ## SHA256: dffa79e6aa993f558e82884abf7bb54bf440ab66ee91d82a27a627f6f2a4ace4 ## GlobalSign Root CA ================== -----BEGIN CERTIFICATE----- MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkGA1UEBhMCQkUx GTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jvb3QgQ0ExGzAZBgNVBAMTEkds b2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAwMDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNV BAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYD VQQDExJHbG9iYWxTaWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDa DuaZjc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavpxy0Sy6sc THAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp1Wrjsok6Vjk4bwY8iGlb Kk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdGsnUOhugZitVtbNV4FpWi6cgKOOvyJBNP c1STE4U6G7weNLWLBYy5d4ux2x8gkasJU26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrX gzT/LCrBbBlDSgeF59N89iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0BAQUF AAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOzyj1hTdNGCbM+w6Dj Y1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE38NflNUVyRRBnMRddWQVDf9VMOyG j/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymPAbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhH hm4qxFYxldBniYUr+WymXUadDKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveC X4XSQRjbgbMEHMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A== -----END CERTIFICATE----- |/8< snip 8<|| |!code| |^ The WASD OpenSSL package provides an example CA verification file. The exact date and source can be found in the opening commentary of the file itself. The contents of this file easily can be pared down to the minimum certificates required for any given site. |^ The bundle may be refreshed at any time using any reliable source. The cURL project provides such a resource suitable for its own use, Apache mod_ssl and WASD. This is sourced from the root certificates used by the Mozilla Foundation for its Firefox product (and others). Mozilla uses a non-PEM format source which must be converted before use by WASD. The cURL site provides this already converted for use with its own utility and made available as a general resource. |simple#| |& |%http://curl.haxx.se/| |& |%http://curl.haxx.se/docs/caextract.html| |!simple| |^ Download the bundle using a command-line tool as in this example |code| $ curl -o ca-bundle_crt.txt https://curl.haxx.se/ca/cacert.pem |!code| or as a save-as dialogue click from your favourite browser and then a transfer onto the VMS system. |simple| |& |%https://curl.haxx.se/ca/cacert.pem|| |!simple| |3X.509 Authorization CGI Variables| |^ CGI variables specific to client certificate authorization are always generated for use by scripts and SSI documents. These along with the general WASD authorization variables are shown in the example below. Note, that due to length of particular items some in this example are displayed wrapped. |code| WWW_AUTH_ACCESS == "READ+WRITE" WWW_AUTH_GROUP == "" WWW_AUTH_REALM == "X509" WWW_AUTH_REALM_DESCRIPTION == "X509 Client Certs" WWW_AUTH_TYPE == "X509" WWW_AUTH_USER == "Mark Daniel, mark.daniel@wasd.vsm.com.au" WWW_AUTH_X509_CIPHER == "RC4-MD5" WWW_AUTH_X509_FINGERPRINT == "10:6C:83:42:89:0A:17:03:AA:A5:17:31:7B:14:5B:F7" WWW_AUTH_X509_ISSUER == "/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=www.verisign.com/repository/RPA Incorp. By Ref.,LIAB.LTD(c)98/CN=VeriSign Class 1 CA Individual Subscriber-Persona Not Validated" WWW_AUTH_X509_KEYSIZE == "128" WWW_AUTH_X509_SUBJECT == "/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=www.verisign.com/repository/RPA Incorp. by Ref.,LIAB.LTD(c)98/OU=Persona Not Validated/OU=Digital ID Class 1 - Netscape /CN=Mark Daniel/Email=mark.daniel@wasd.vsm.com.au" WWW_REMOTE_USER == "106C8342890A1703AAA517317B145BF7" |!code| |^ Other CGI variables optionally may be enabled using WASD_CONFIG_MAP mapping rules. See |link|X.509 Authorization CGI Variables||. Specific client certificate variables providing the details of such certificates are available with SSLCGI=apache_mod_ssl. These are of course in addition to the more general apache_mod_ssl variables described in the above section. Note that where some ASN.1 records are duplicated (as in SSL_CLIENT_S_DN) some variables will contain newline characters (0x10) between those elements (e.g. SSL_CLIENT_S_DN_OU). The line breaks in this example do not necesarily reflect those characters. |code| WWW_SSL_CIPHER == "TLS_AES_256_GCM_SHA384" WWW_SSL_CIPHER_ALGKEYSIZE == "256" WWW_SSL_CIPHER_USEKEYSIZE == "256" WWW_SSL_PROTOCOL == "TLSv1.3" WWW_SSL_SERVER_A_KEY == "rsaEncryption" WWW_SSL_SERVER_A_SIG == "sha256WithRSAEncryption" WWW_SSL_SERVER_E_AUTHORITY_INFORMATION_ACCESS == "OCSP - URI:http://ocsp.int-x3.letsencrypt.org.CA Issuers 8< snip 8< WWW_SSL_SERVER_E_AUTHORITY_INFORMATION_ACCESS_URI == "http://ocsp.int-x3.letsencrypt.org" WWW_SSL_SERVER_E_AUTHORITY_INFORMATION_ACCESS_URI__2 == "http://cert.int-x3.letsencrypt.org/" WWW_SSL_SERVER_E_CT_PRECERTIFICATE_SCTS == "Signed Certificate Timestamp:. Version : v1 (0x0). Log ID : 8< snip 8< WWW_SSL_SERVER_E_X509V3_AUTHORITY_KEY_IDENTIFIER == "keyid:A8:4A:6A:63:04:7D:DD:BA:E6:D1:39:B7:A6:45:65:EF:F3:A8:EC:A1." WWW_SSL_SERVER_E_X509V3_AUTHORITY_KEY_IDENTIFIER_KEYID == "A8:4A:6A:63:04:7D:DD:BA:E6:D1:39:B7:A6:45:65:EF:F3:A8:EC:A1" WWW_SSL_SERVER_E_X509V3_BASIC_CONSTRAINTS == "CA:FALSE" WWW_SSL_SERVER_E_X509V3_BASIC_CONSTRAINTS_CA == "FALSE" WWW_SSL_SERVER_E_X509V3_CERTIFICATE_POLICIES == "Policy: 2.23.140.1.2.1.Policy: 1.3.6.1.4.1.44947.1.1.1. 8< snip 8< WWW_SSL_SERVER_E_X509V3_CERTIFICATE_POLICIES_CPS == " http://cps.letsencrypt.org" WWW_SSL_SERVER_E_X509V3_CERTIFICATE_POLICIES_POLICY == " 2.23.140.1.2.1" WWW_SSL_SERVER_E_X509V3_CERTIFICATE_POLICIES_POLICY__2 == " 1.3.6.1.4.1.44947.1.1.1" WWW_SSL_SERVER_E_X509V3_EXTENDED_KEY_USAGE == "TLS Web Server Authentication, TLS Web Client Authentication" WWW_SSL_SERVER_E_X509V3_KEY_USAGE == "Digital Signature, Key Encipherment" WWW_SSL_SERVER_E_X509V3_SAN == "dNSName:the.host.name..dNSName:the.host.name" WWW_SSL_SERVER_E_X509V3_SUBJECT_ALTERNATIVE_NAME == "dNSName:the.host.name..dNSName:the.host.name" WWW_SSL_SERVER_E_X509V3_SUBJECT_KEY_IDENTIFIER == "4E:6A:0B:56:F0:EF:1B:1E:71:E1:33:53:A0:39:32:D3:0C:D6:3C:0C" WWW_SSL_SERVER_I_DN == "/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3" WWW_SSL_SERVER_I_DN_C == "US" WWW_SSL_SERVER_I_DN_CN == "Let's Encrypt Authority X3" WWW_SSL_SERVER_I_DN_O == "Let's Encrypt" WWW_SSL_SERVER_M_SERIAL == "03AC67E421D5E26AA843A14F50343FEB1F84" WWW_SSL_SERVER_M_VERSION == "3" WWW_SSL_SERVER_S_DN == "/CN=the.host.name" WWW_SSL_SERVER_S_DN_CN == "the.host.name" WWW_SSL_SERVER_V_END == "Jul 17 13:50:24 2020 GMT" WWW_SSL_SERVER_V_START == "Apr 18 13:50:24 2020 GMT" WWW_SSL_SESSION_ID == "533d71a813a1ee8c5c68ae30c4cd05ac3b673ee9b04ac04567cad18418730dfe" WWW_SSL_TLS_ALPN == "h2" WWW_SSL_TLS_SNI == "the.host.name" WWW_SSL_VERSION_INTERFACE == "HTTPd-WASD/11.5.0 OpenVMS/AXP SSL" WWW_SSL_VERSION_LIBRARY == "OpenSSL 1.1.1c 28 May 2019" |!code| |2Certificate Management| |^ This is not a tutorial on X.509 certificates and their management. Refer to the listed references, |link|Transport Layer Security||, for further information on this aspect. It does provide some basic guidelines. |^ Certificates identify something or someone, associating a public cryptographic key with the identity of the certificate holder. It includes a distinguished name, identification and signature of the certificate authority (CA, the issuer and guarantor of the certificate), and the period for which the certificate is valid, possibly with other, additional information. |^ The three types of certificates of interest here should not be confused. |bullet| |item| |*CA |-| | The Certificate Authority identifies the |/authority||, or organization, that issues a certificate. |item| |*Server |-| | Identifies a particular end-service. Its value as an guarantee of identity is founded in the |/authority| of the organization that issues the certificate. It is the certificate specified to the server at startup. |item| |*Client |-| | Identifies a particular client to a server via SSL (client authentication). Typically, the identity of the client is assumed to be the same as the identity of a human being. Again, its value as an guarantee of identity is founded in the |/authority| of the organization that issues the certificate. |!bullet| |^ The various OpenSSL tools are available for management of all of these certificate types in each of the three SSL environments. |bullet| |item| The VSI SSL111 product provides the "SSL Certificate Tool" procedure can be used to perform most required certificate management tasks from a menu-driven interface. |code| $ @SSL111$COM:SSL111$CERT_TOOL.COM |*SSL Certificate Tool|| |*Main Menu|| 1. View a Certificate 2. View a Certificate Signing Request 3. Create a Certificate Signing Request 4. Create a Self-Signed Certificate 5. Create a CA (Certification Authority) Certificate 6. Sign a Certificate Signing Request 7. Revoke a Certificate 8. Create a Certificate Revocation List 9. Hash Certificates 10. Hash Certificate Revocations 11. Exit Enter Option: |!code| |item| The standard OpenSSL toolkit provides a number of command-line tools for creation and management of X.509 certificates. |item| Or if you prefer something a little less arcane than the (ever so useful) command-line | |note| |0not really an endorsement but| |^ XCA is a |*GUI application| intended for creating and managing X.509 certificates, certificate requests, RSA, DSA and EC private keys, Smartcards and CRLs. It uses the OpenSSL library for the cryptographic operations. The application is available for Linux, macOS and Windows, as well as source code. |simple#| |& |%https://hohnstaedt.de/xca| |& |%https://sourceforge.net/projects/xca/| |!simple| |!note| |!bullet| |3Server Certificate| |^ The server uses a certificate to establish its identity during the initial phase of the SSL protocol exchange. Each server should have a unique certificate. An example certificate is provided with the WASD OpenSSL package. If this is not available (for instance when using the VSI SSL111 product) then the server will fallback to an internal, default certificate that allows SSL functionality even when no external certification is available. If a "live" SSL site is required a unique certificate issued by a third-party Certificate Authority is desirable. |note| |0Let's Encrypt| Self-signing certificates as described below has a number of shortcomings for general web server certification. Fortunately |*Let's Encrypt|| makes it possible automatically to obtain and maintain a browser-trusted certificate, simply, and |*at no cost||. This is accomplished by running a certificate management agent on the web server. The |_WASD Certificate Management Environment| (wuCME) may be used to perform this function on VMS. |^ See |*wuCME| on the WASD download page at |%https://wasd.vsm.com.au/wasd/#wucme|https://wasd.vsm.com.au/wasd/| |!note| |0Self-Signed Certificates| |^ A less satisfactory alternative to obtaining one of these certificates is provided by the WASD support DCL procedures, which are quick hacks to ease the production of certificates on an ad hoc basis. In all cases it is preferable to directly use the utilities provided with OpenSSL, but the documentation tends to be rather sparse. |^ The VSI |=SSL111$COM:SSL111$CERT_TOOL.COM| described above can create self-signed certificates. |^ |*_Also note that the WASD server dynamically generates a self-signed certificate| for TLS services that otherwise do not have a configured server certificate. This is largely for testing a server immediately after installation (e.g. using |*.@WASD_ROOT:[INSTALL]DEMO SSL| at the command-line). This certificate suffers all the short-comings of self-signed certificates with modern browsers (post-2019) but is better than no certificate all all. Interestingly, |*Incognito/[In]Private instances| of a browser are often more relaxed about accepting certificates with recognised security deficiencies (e.g. unknown Certificate Authority signing). At least at the time of writing. |0Loading Authority Certificates|| |^ The first requirement may be a tailored "Certificate Authority" certificate. As the Certificate Authority is non-authoritative (not trying to be too oxymoronic, i.e. not a well-known CA) these certificates have little value except to allow SSL transactions to be established with trusting clients. More commonly "Server Certificates" for specific host names are required. |^ CA certificates can be loaded into browsers to allow sites using that CA to be accessed by that browser without further dialog. Browsers commonly invoke a server certificate load dialog when encountering a site using a valid but unknown server certificate. |^ A manual load is accomplished by requesting the certificate in a format appropriate to the particular browser. This triggers a browser dialog with the user to confirm or refuse the loading of that certificate into the browser Certificate Authority database. |^ To facilitate loading CA certificates into a browser ensure the following entries are contained in the HTTP$CONFIG configuration file: |code| [AddIcon] /httpd/-/binary.gif [BIN] application/x-x509-ca-cert [AddType] .CRT application/x-x509-ca-cert - DER certifcate (MSIE) .PEM application/x-x509-ca-cert - Privacy Enhanced Mail certificate |!code| |^ Then just provide a link to the required certificate file(s), and click. |0Changing Server Certificates|| |^ If a site's server (or CA certificate) is changed and the server restarted any executing browsers will probably complain (Netscape Navigator reports an I/O error). In this case open the browser's certificate database and delete any relevant, permanently stored certificate entry, then close and restart the browser. The next access should initiate the server certificate dialog, or the CA certificate may be explicitly reloaded. |3Certificate Signing Request| |^ Recognised Certificate Authorities (CAs) such as Thawte and VeriSign publish lists of requirements for obtaining a server certificate. These often include such documents required to prove organisational name and the right to use the domain name being requested. Check the particular vendor for the exact requirements. |^ In addition, a document containing the site's private key is required. This is known as the Certificate Signing Request (CSR) and must be generated digitally at the originating site. |^ Using the VSI SSL111 for OpenVMS product "SSL Certificate Tool" described in |link|Certificate Management| a CSR can easily be generated using its menu-driven interface. The alternative is using a command-line interface tool. |^ The following instructions provide the basics for generating a CSR at the command-line in the WASD and generally the any OpenSSL environment (including the VSI SSL111 for OpenVMS product). |number| |item| Change to a secure directory. The following is a suggestion. |code| $ SET DEFAULT WASD_ROOT:[LOCAL] |!code| |item| Assign a foreign verb for the OPENSSL application. The location may vary a little depending on which OpenSSL package you have installed. See |link|OPENSSL.EXE Application||. |item| Specify a source of lots of "random" data (can be any big file for the purposes of this exercise). |code| $ RANDFILE = "WASD_EXE:HTTPD_SSL.EXE" |!code| |item| Find the template configuration file. You will need to specify this location in a step described below. Should be something like the following. |code| WASD_ROOT:[SRC.OPENSSL-|/version||.WASD]TEMPLATE.CNF |!code| |item| Generate your private key (RANDFILE data is used by this). The output from this looks something like what's shown. Notice the pass phrase prompts. |*This is your private key, don't forget it!|| |code| $ OPENSSL GENRSA -DES3 -OUT SERVER.KEY 1024 Generating RSA private key, 1024 bit long modulus .....++++++ ......++++++ e is 65537 (0x10001) Enter PEM pass phrase: Verifying password - Enter PEM pass phrase: |!code| |item| Generate the Certificate Signing Request using syntax similar to the following (this is where you are required to specify the location of the configuration template). Note that there are quite a few fields - |*GET THEM RIGHT!| They need to be unique and local - they're your distinguishing name (DN). "Common Name" is the host you want the certificate for. It can be a fully qualifier host name (e.g. "klaatu.local.net"), or a local |/wildcard| (e.g. "*.local.net") for which you may pay more. |code| $ OPENSSL REQ -NEW -KEY SERVER.KEY -OUT SERVER.CSR -CONFIG - WASD_ROOT:[SRC.OPENSSL-0_9_6B.WASD]TEMPLATE.CNF Using configuration from template.cnf Enter PEM pass phrase: You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [AU]:AU State or Province Name (full name) [Some-State]:South Australia Locality Name (eg, city) []:Adelaide Organization Name (eg, company) [Internet Widgits Pty Ltd]:Example Organizational Unit Name (eg, section) []:WASD Common Name (eg, YOUR name) []:klaatu.local.net Email Address []:Mark.Daniel@wasd.vsm.com.au Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []: |!code| |item| That's it! You should have two files in your default directory. |code| SERVER.CSR;1 2 14-MAR-2002 04:38:26.15 SERVER.KEY;1 2 14-MAR-2002 04:31:38.76 |!code| |^ Keep the SERVER.KEY file secure. You'll need it when you receive the certificate back from the CA. |^ The SERVER.CSR is what you send to the CA (usually by mail or Web form). It looks something like the following |code| $ TYPE SERVER.CSR -----BEGIN CERTIFICATE REQUEST----- MIIBPTCB6AIBADCBhDELMAkGA1UEBhMCWkExFTATBgNVBAgTDFdlc3Rlcm4gQ2Fw ZTESMBAGA1UEBxMJQ2FwZSBUb3duMRQwEgYDVQQKEwtPcHBvcnR1bml0aTEYMBYG A1UECxMPT25saW5lIFNlcnZpY2VzMRowGAYDVQQDExF3d3cuZm9yd2FyZC5jby56 YTBaMA0GCSqGSIb3DQEBAQUAA0kAMEYCQQDT5oxxeBWu5WLHD/G4BJ+PobiC9d7S 6pDvAjuyC+dPAnL0d91tXdm2j190D1kgDoSp5ZyGSgwJh2V7diuuPlHDAgEDoAAw DQYJKoZIhvcNAQEEBQADQQBf8ZHIu4H8ik2vZQngXh8v+iGnAXD1AvUjuDPCWzFu pReiq7UR8Z0wiJBeaqiuvTDnTFMz6oCq6htdH7/tvKhh -----END CERTIFICATE REQUEST----- |!code| |^ You can see the details of this file using |code| $ OPENSSL RSA -NOOUT -TEXT -IN SERVER.CSR |!code| |!number| |0After Receiving The Certificate|| |^ Once the signed certificate has been issued by the Certificate Authority it can be placed directly into the server configuration directory, usually WASD_ROOT:[LOCAL], and configured for use from there. Using the certificate direct from the CA requires that the private key password be given to the server each time (|link|SSL Private Key||). It is possible to embed the password into the certificate key so that this is not required. |^ |*Remember to keep original files secure, only work on copies!|| |number| |item| Assign a foreign verb for the OPENSSL application. The location may vary a little depending on which OpenSSL package you have installed. |code| $ OPENSSL == "$WASD_ROOT:[SRC.OPENSSL-|/version||.AXP.EXE.APPS]OPENSSL.EXE" |!code| |^ When using the VSI SSL111 product or other OpenSSL toolkit the verb may already be available. |code| $ SHOW SYMBOL OPENSSL OPENSSL == "$ SSL111$EXE:OPENSSL" |!code| |item| Go to wherever you want to do the work. |code| $ SET DEFAULT WASD_ROOT:[LOCAL] |!code| |item| You may require these additional steps (based on user experience): |bullet| |item| VeriSign sent certificate with headers like this: |code| -----BEGIN PKCS #7 SIGNED DATA----- -----END PKCS #7 SIGNED DATA----- |!code| |^ Using an editor, ensure the header/trailer looks this: |code| -----BEGIN PKCS7----- -----END PKCS7----- |!code| |item| Then into the required intermediate format: |code| $ OPENSSL pkcs7 -print_certs -in SERVER.CERT -outform DER -out CERTIFICATE.PEM |!code| |item| A |/readable| version of the new file can be viewed using: |code| $ OPENSSL x509 -noout -text -in CERTIFICATE.PEM |!code| |!bullet| |item| Using the original key file embed your password into a copy. When prompted "Enter PEM pass phrase:" enter the password. |code| $ OPENSSL rsa -in SERVER.KEY -out WORK.PEM |!code| |item| Append this password-embedded key file to your certificate file. |code| $ COPY CERTIFICATE.PEM,WORK.PEM CERTIFICATE.PEM;0 |!code| |item| Delete the temporary file. |code| $ DELETE WORK.PEM;* |!code| |!number| |2SSL CGI Variables| |^ CGI variables specific to SSL transactions optionally may be enabled using WASD_CONFIG_MAP mapping rules. (See |link%|../config/##Request Processing Configuration++of++WASD Configuration||). The may be done on a specific per-path or general CGI basis. In the following examples, due to length of particular items, some in this example are displayed wrapped. Also, where some ASN.1 records are duplicated (as in SSL_CLIENT_S_DN), some variables will contain newline characters (0x10) between those elements (e.g. SSL_CLIENT_S_DN_OU). The line breaks in the examples do not necesarily reflect those characters. |0set /path/* SSLCGI=apache_mod_ssl| |^ |code| WWW_SSL_CIPHER == "TLS_AES_256_GCM_SHA384" WWW_SSL_CIPHER_ALGKEYSIZE == "256" WWW_SSL_CIPHER_USEKEYSIZE == "256" WWW_SSL_PROTOCOL == "TLSv1.3" WWW_SSL_SERVER_A_KEY == "rsaEncryption" WWW_SSL_SERVER_A_SIG == "sha256WithRSAEncryption" WWW_SSL_SERVER_E_AUTHORITY_INFORMATION_ACCESS == "OCSP - URI:http://ocsp.int-x3.letsencrypt.org.CA Issuers 8< snip 8< WWW_SSL_SERVER_E_AUTHORITY_INFORMATION_ACCESS_URI == "http://ocsp.int-x3.letsencrypt.org" WWW_SSL_SERVER_E_AUTHORITY_INFORMATION_ACCESS_URI__2 == "http://cert.int-x3.letsencrypt.org/" WWW_SSL_SERVER_E_CT_PRECERTIFICATE_SCTS == "Signed Certificate Timestamp:. Version : v1 (0x0). Log ID : 8< snip 8< WWW_SSL_SERVER_E_X509V3_AUTHORITY_KEY_IDENTIFIER == "keyid:A8:4A:6A:63:04:7D:DD:BA:E6:D1:39:B7:A6:45:65:EF:F3:A8:EC:A1." WWW_SSL_SERVER_E_X509V3_AUTHORITY_KEY_IDENTIFIER_KEYID == "A8:4A:6A:63:04:7D:DD:BA:E6:D1:39:B7:A6:45:65:EF:F3:A8:EC:A1" WWW_SSL_SERVER_E_X509V3_BASIC_CONSTRAINTS == "CA:FALSE" WWW_SSL_SERVER_E_X509V3_BASIC_CONSTRAINTS_CA == "FALSE" WWW_SSL_SERVER_E_X509V3_CERTIFICATE_POLICIES == "Policy: 2.23.140.1.2.1.Policy: 1.3.6.1.4.1.44947.1.1.1. 8< snip 8< WWW_SSL_SERVER_E_X509V3_CERTIFICATE_POLICIES_CPS == " http://cps.letsencrypt.org" WWW_SSL_SERVER_E_X509V3_CERTIFICATE_POLICIES_POLICY == " 2.23.140.1.2.1" WWW_SSL_SERVER_E_X509V3_CERTIFICATE_POLICIES_POLICY__2 == " 1.3.6.1.4.1.44947.1.1.1" WWW_SSL_SERVER_E_X509V3_EXTENDED_KEY_USAGE == "TLS Web Server Authentication, TLS Web Client Authentication" WWW_SSL_SERVER_E_X509V3_KEY_USAGE == "Digital Signature, Key Encipherment" WWW_SSL_SERVER_E_X509V3_SAN == "dNSName:the.host.name..dNSName:the.host.name" WWW_SSL_SERVER_E_X509V3_SUBJECT_ALTERNATIVE_NAME == "dNSName:the.host.name..dNSName:the.host.name" WWW_SSL_SERVER_E_X509V3_SUBJECT_KEY_IDENTIFIER == "4E:6A:0B:56:F0:EF:1B:1E:71:E1:33:53:A0:39:32:D3:0C:D6:3C:0C" WWW_SSL_SERVER_I_DN == "/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3" WWW_SSL_SERVER_I_DN_C == "US" WWW_SSL_SERVER_I_DN_CN == "Let's Encrypt Authority X3" WWW_SSL_SERVER_I_DN_O == "Let's Encrypt" WWW_SSL_SERVER_M_SERIAL == "03AC67E421D5E26AA843A14F50343FEB1F84" WWW_SSL_SERVER_M_VERSION == "3" WWW_SSL_SERVER_S_DN == "/CN=the.host.name" WWW_SSL_SERVER_S_DN_CN == "the.host.name" WWW_SSL_SERVER_V_END == "Jul 17 13:50:24 2020 GMT" WWW_SSL_SERVER_V_START == "Apr 18 13:50:24 2020 GMT" WWW_SSL_SESSION_ID == "533d71a813a1ee8c5c68ae30c4cd05ac3b673ee9b04ac04567cad18418730dfe" WWW_SSL_TLS_ALPN == "h2" WWW_SSL_TLS_SNI == "the.host.name" WWW_SSL_VERSION_INTERFACE == "HTTPd-WASD/11.5.0 OpenVMS/AXP SSL" WWW_SSL_VERSION_LIBRARY == "OpenSSL 1.1.1c 28 May 2019" |!code| |^ The Apache |/mod_ssl| client certificate details described in |link|X.509 Authorization CGI Variables| above are not shown in the above example but would be included if the request was X.509 authenticated. |^ X509 certificate extensions are in general visible from WATCH and accessible via CGI variables when enabled using SET |/SSLCGI=apache_mod_ssl_extens| and |/SSLCGI=apache_mod_ssl_client| path mappings. |2SSL Service Evaluation| |^ This section is just the barest introduction to a significant topic. |0Qualys SSL Lab|| |^ "How well do you know SSL? If you want to learn more about the technology that protects the Internet, you've come to the right place." |^+ |%https://www.ssllabs.com/| |^ Not necessarily an endorsement by WASD but a useful resource in itself. |^ Provides a |/free and unencumbered||, comprehensive SSL Server test service |^+ |%https://www.ssllabs.com/ssltest/| |^ reporting on certificate status, protocol version, cipher suites, handshakes with various simulated clients, and protocol details including known vulnerabilities. It also summarises the report with a colour-coded rating. |0At Home|| |^ So to speak. |^ The OPENSSL command-line application (|link|OPENSSL.EXE Application)||) provides a configurable client for checking and testing various aspects of server configuration and behaviour. The basic operation represented by the command-line |code| $ openssl s_client -host |/| -port 443 |!code| provides a comprehensive report including certificates and certificate chain, the protocol version and cipher negotiated, along with more esoteric elements of TLS/SSL. Some data have been 8< snipped 8< for brevity in the following example. |code| $ openssl s_client -host klaatu.private -port 443 WARNING: can't open config file: SSLROOT:[000000]openssl.cnf CONNECTED(00000003) depth=0 C = AU, ST = SA, L = Adelaide, O = WASD Server Cert, OU 8< snip 8< verify error:num=20:unable to get local issuer certificate verify return:1 depth=0 C = AU, ST = SA, L = Adelaide, O = WASD Server Cert, OU 8< snip 8< verify error:num=27:certificate not trusted verify return:1 depth=0 C = AU, ST = SA, L = Adelaide, O = WASD Server Cert, OU 8< snip 8< verify error:num=21:unable to verify the first certificate verify return:1 --- Certificate chain 0 s:/C=AU/ST=SA/L=Adelaide/O=WASD Server Cert/OU=OpenSSL 1.0.1 8< snip 8< i:/C=AU/ST=SA/L=Adelaide/O=WASD CA Cert/OU=OpenSSL 1.0.1j Te 8< snip 8< --- Server certificate -----BEGIN CERTIFICATE----- MIIFsjCCBJqgAwIBAgIBBDANBgkqhkiG9w0BAQQFADCBtjELMAkGA1UEBhMCQVUx 8< snip 8< pErvrfr69iDbJbhO+mRmIkZIXHc5CFV/M1zzLD5240ixxu/d6nAUBhGba0W4Kste x1SgLJ0BqFTjegxuHRXkK5lOlY11Hw== -----END CERTIFICATE----- subject=/C=AU/ST=SA/L=Adelaide/O=WASD Server Cert/OU=OpenSSL 1. 8< snip 8< issuer=/C=AU/ST=SA/L=Adelaide/O=WASD CA Cert/OU=OpenSSL 1.0.1j 8< snip 8< --- No client certificate CA names sent --- SSL handshake has read 1791 bytes and written 625 bytes ---|"|| New, TLSv1/SSLv3, Cipher is AES256-GCM-SHA384 Server public key is 2048 bit|"|| Secure Renegotiation IS supported Compression: NONE Expansion: NONE SSL-Session:|"|| Protocol : TLSv1.2 Cipher : AES256-GCM-SHA384|"|| Session-ID: 61FEC1629DA3E675AA124223CDB9CB5AB7701D872E85E15 8< snip 8< Session-ID-ctx: Master-Key: F4260DFE9A7370B3EA85D22D89DB8A7925C655159C3C509 8< snip 8< Key-Arg : None PSK identity: None PSK identity hint: None SRP username: None TLS session ticket lifetime hint: 300 (seconds) TLS session ticket: 0000 - 63 d6 2a 84 19 fe f6 9a-13 60 e1 8a 65 dd f9 fc c.*......`..e... 8< snip 8< 00a0 - 9a 2d 29 9b 8e aa ab 69-11 0d 45 ed 63 48 f5 4f .-)....i..E.cH.O Start Time: 1415828121 Timeout : 300 (sec) Verify return code: 21 (unable to verify the first certificate) --- 8< snip 8< |!code| |^ A "bad select 38" is a VMS (C-RTL) limitation of earlier versions of OpenSSL and is not present in later versions or on other platforms, and the default use of -s_client will prompt for an HTTP request line, send that to the server, and report the response. |^ Checking whether a specific protocol version is enabled on a site: |code| $ openssl s_client -ssl2 -host |/| -port 443 $ openssl s_client -ssl3 -host |/| -port 443 $ openssl s_client -tls1 -host |/| -port 443 $ openssl s_client -tls1_1 -host |/| -port 443 $ openssl s_client -tls1_2 -host |/| -port 443 $ openssl s_client -tls1_3 -host |/| -port 443 |!code| |^ The following example shows a server test where the protocol version is NOT supported. |code| $ openssl s_client -ssl3 -host klaatu.private -port 443 8< snip 8< SSL handshake has read 7 bytes and written 0 bytes ---|"|| New, (NONE), Cipher is (NONE)|"|| Secure Renegotiation IS NOT supported Compression: NONE Expansion: NONE SSL-Session:|"style="background-color:yellow">|| Protocol : SSLv3 Cipher : 0000|"|| 8< snip 8< |!code| |0TLS Version 1.3| |9test TLS Version 1.3| |^ Server TLSv1.3 response may be checked using an OPENSSL.EXE v1.1.1 or later. |code| $ OPENSSL version OpenSSL 1.1.1 11 Sep 2018 $ OPENSSL s_client --host wasd.xxxxxxxxxx.xxx --port 443 CONNECTED(00000003) depth=1 C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3 verify error:num=20:unable to get local issuer certificate --- Certificate chain 0 s:CN = wasd.xxxxxxxxx.xxx i:C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3 1 s:C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3 i:O = Digital Signature Trust Co., CN = DST Root CA X3 --- Server certificate -----BEGIN CERTIFICATE----- MIIHJDCCBgygAwIBAgISA8gmjxQDyTgXeAfy7ehpvXeBMA0GCSqGSIb3DQEBCwUA 8< snip 8< rL2n3YpsP2xuCwV6ZT+etAl1IrtmXuC9tnG2QRVtVJn7wyUacUTz3XuKagS9w6Bo be0oPuGGnT0= -----END CERTIFICATE----- subject=CN = wasd.xxxxxxxxx.xxx issuer=C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3 --- No client certificate CA names sent Peer signing digest: SHA256 Peer signature type: RSA-PSS Server Temp Key: X25519, 253 bits --- SSL handshake has read 3827 bytes and written 393 bytes Verification error: unable to get local issuer certificate --- |"|| New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384|"|| Server public key is 4096 bit Secure Renegotiation IS NOT supported Compression: NONE Expansion: NONE No ALPN negotiated Early data was not sent Verify return code: 20 (unable to get local issuer certificate) --- --- Post-Handshake New Session Ticket arrived: SSL-Session: |"|| Protocol : TLSv1.3 Cipher : TLS_AES_256_GCM_SHA384|"|| Session-ID: 0074FBDFD12EF693B0419611204FF9EC6BFA3C006A2A7D312A9435CF7D79FE3A Session-ID-ctx: Resumption PSK: 3176C237B08F4E83B7AC32CBC79C8B79CC8FBA20837419682C4A97998898ECDE13F5254E0820C977AEC0B63C9B4B21C8 PSK identity: None PSK identity hint: None SRP username: None TLS session ticket lifetime hint: 5400 (seconds) TLS session ticket: 0000 - a7 99 08 ba aa 75 1d 53-68 c4 66 fb 5e 43 5e b2 .....u.Sh.f.^C^. 8< snip 8< 00d0 - 5d a5 3c 10 5e 4c 41 4b-bb 15 c9 5c 08 fe e1 1f ].<.^LAK...\\.... Start Time: 1537620807 Timeout : 7200 (sec) Verify return code: 20 (unable to get local issuer certificate) Extended master secret: no Max Early Data: 0 --- read R BLOCK --- Post-Handshake New Session Ticket arrived: SSL-Session: |"|| Protocol : TLSv1.3 Cipher : TLS_AES_256_GCM_SHA384|"|| Session-ID: 8DB922A11FD02889CED45C4D125C5A55B5F76B42B49826EF39CA265988FA4FA9 Session-ID-ctx: Resumption PSK: 60F73CE06DDDA5737B607A20DF7E13D85CBFFD695DB98B53B9AF09A0DABE6B34A0F50F86E2578845F1E0EA799B014B42 PSK identity: None PSK identity hint: None SRP username: None TLS session ticket lifetime hint: 5400 (seconds) TLS session ticket: 0000 - a7 99 08 ba aa 75 1d 53-68 c4 66 fb 5e 43 5e b2 .....u.Sh.f.^C^. 8< snip 8< 00d0 - 92 32 8d 2c 9c 22 54 b1-6e 24 9a c3 de 1a de a2 .2.,."T.n$...... Start Time: 1537620807 Timeout : 7200 (sec) Verify return code: 20 (unable to get local issuer certificate) Extended master secret: no Max Early Data: 0 --- read R BLOCK read:errno=0 |!code| |2SSL References| |^ The following provide a starting-point for investigating SSL and OpenSSL further (verified available at time of publication). |bullet| |item| |%http://www.openssl.org/| |^- OpenSSL Project. This site is the prime source for the full toolkit, documentation, related links, news and support via mailing lists, etc. |^- |%http://wiki.openssl.org/| |^- OpenSSL Wiki |item| |%https://www.oreilly.com/library/view/high-performance-browser/9781449344757/ch04.html| |^- Ilya Grigorik's - Transport Layer Security (TLS) |^- From the excellent |%https://www.oreilly.com/library/view/high-performance-browser/9781449344757/| |item| |%http://en.wikipedia.org/wiki/Transport_Layer_Security| |^- Wikipedia - Transport Layer Security (SSL) |item| |%https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/\ Transport_Layer_Protection_Cheat_Sheet.md| |^- OWASP Transport Layer Protection Cheat Sheet |item| |%http://en.wikipedia.org/wiki/OpenSSL| |^- Wikipedia - OpenSSL |item| |%http://en.wikipedia.org/wiki/Public_key_infrastructure| |^- Wikipedia - Public-Key Infrastructure |item| |%https://www.ssllabs.com/| |^- Qualys SSL Labs |^- |%https://www.ssllabs.com/ssltest/| |^- SSL Server Test |item| |%https://www.feistyduck.com/books/openssl-cookbook/| |^- OpenSSL Cookbook by Ivan Ristic (of Qualys Labs) |^- As promoted by OpenSSL.org |item| |%https://www.openssl.org/docs/manmaster/man1/openssl.html| |^- |%https://wiki.openssl.org/index.php/Command_Line_Utilities| |^- OPENSSL.EXE application |item| |%http://hohnstaedt.de/xca| |^- |%https://sourceforge.net/projects/xca/| |^- XCA is a GUI application intended for creating and managing X.509 certificates, certificate requests, RSA, DSA and EC private keys, Smartcards and CRLs. |!bullet|