diff --git a/CHANGELOG.md b/CHANGELOG.md index db4192a..3ba0ee7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,7 +47,7 @@ server = GeminiServer(app) server.run() ``` -Check out the updated examples in the examples/ directory for more details. +Check out the updated examples in the *examples/* directory for more details. #### TLS Client Certificates @@ -65,12 +65,16 @@ variable. #### Other Changes - A client certificate can now have an empty ``commonName`` field. -- ``JetforceApplication``: Named capture groups in a route's regex pattern - will now be passed as keyword arguments to the wrapped function. See +- For the ``JetforceApplication``, named capture groups in a route's regex + pattern will now be passed as keyword arguments to the wrapped function. See examples/pagination.py for an example of how to use this feature. -- A new ``CompositeApplication`` class is included to support virtual hosting - by combining multiple applications behind the same jetforce server. See - examples/vhost.py for an example of how to use this class. +- A ``CompositeApplication`` class is now included to support virtual hosting + by composing multiple applications behind the same jetforce server. See + examples/vhost.py for an example of how to use this feature. +- CGI variables - ``SCRIPT_NAME`` and ``PATH_INfO`` have been changed to match + their intended usage as defined in RFC 3875. +- CGI variables - ``TLS_CIPHER`` and ``TLS_VERSION`` have been added and + contain information about the established TLS connection. ### v0.2.3 (2020-05-24) diff --git a/README.md b/README.md index 0246979..ed9d459 100644 --- a/README.md +++ b/README.md @@ -146,6 +146,8 @@ the request using environment variables: | REMOTE_ADDR | Client IP address. | ``10.10.0.2`` | | REMOTE_HOST | Client IP address (alias for REMOTE_ADDR). | ``10.10.0.2`` | | SERVER_PORT | Server port number. | ``1965`` | +| TLS_CIPHER | TLS cipher that was negotiated. | ``TLS_AES_256_GCM_SHA384``| +| TLS_VERSION | TLS version that was negotiated. | ``TLSv1.3`` | Additional CGI variables will also be included when the connection uses a TLS client certificate: @@ -158,8 +160,6 @@ Additional CGI variables will also be included when the connection uses a TLS cl | TLS_CLIENT_NOT_AFTER | Certificate expiration date. | ``2021-04-05T04:18:22Z`` | | TLS_CLIENT_SERIAL_NUMBER | Certificate serial number. | ``73629018972631`` | | TLS_CLIENT_VERIFIED | Was the certificate verified by OpenSSL? | ``0`` (verified) / ``1`` (not verified) | -| TLS_CIPHER | TLS cipher that was negotiated. | ``TLS_AES_256_GCM_SHA384``| -| TLS_VERSION | TLS version that was negotiated. | ``TLSv1.3`` | The CGI script must then write the gemini response to the *stdout* stream. This includes the status code and meta string on the first line, and the diff --git a/jetforce/protocol.py b/jetforce/protocol.py index 3863466..2a67e08 100644 --- a/jetforce/protocol.py +++ b/jetforce/protocol.py @@ -129,6 +129,7 @@ class GeminiProtocol(LineOnlyReceiver): The TLS variable names borrow from the GLV-1.12556 server. """ url_parts = urllib.parse.urlparse(self.url) + conn = self.transport.getHandle() environ = { "GEMINI_URL": self.url, "HOSTNAME": self.server.hostname, @@ -139,6 +140,8 @@ class GeminiProtocol(LineOnlyReceiver): "SERVER_PORT": str(self.client_addr.port), "SERVER_PROTOCOL": "GEMINI", "SERVER_SOFTWARE": f"jetforce/{__version__}", + "TLS_CIPHER": conn.get_cipher_name(), + "TLS_VERSION": conn.get_protocol_version_name(), "client_certificate": None, } @@ -146,7 +149,6 @@ class GeminiProtocol(LineOnlyReceiver): if cert: x509_cert = cert.to_cryptography() cert_data = inspect_certificate(x509_cert) - conn = self.transport.getHandle() environ.update( { "client_certificate": x509_cert, @@ -158,8 +160,6 @@ class GeminiProtocol(LineOnlyReceiver): "TLS_CLIENT_SERIAL_NUMBER": cert_data["serial_number"], # Grab the value that was stashed during the TLS handshake "TLS_CLIENT_VERIFIED": getattr(conn, "verified", False), - "TLS_CIPHER": conn.get_cipher_name(), - "TLS_VERSION": conn.get_protocol_version_name(), } ) return environ