Include TLS connection info variables with all requests

This commit is contained in:
Michael Lazar 2020-05-25 23:52:11 -04:00
parent c794384248
commit c09d0cb47e
3 changed files with 15 additions and 11 deletions

View File

@ -47,7 +47,7 @@ server = GeminiServer(app)
server.run() 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 #### TLS Client Certificates
@ -65,12 +65,16 @@ variable.
#### Other Changes #### Other Changes
- A client certificate can now have an empty ``commonName`` field. - A client certificate can now have an empty ``commonName`` field.
- ``JetforceApplication``: Named capture groups in a route's regex pattern - For the ``JetforceApplication``, named capture groups in a route's regex
will now be passed as keyword arguments to the wrapped function. See 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. examples/pagination.py for an example of how to use this feature.
- A new ``CompositeApplication`` class is included to support virtual hosting - A ``CompositeApplication`` class is now included to support virtual hosting
by combining multiple applications behind the same jetforce server. See by composing multiple applications behind the same jetforce server. See
examples/vhost.py for an example of how to use this class. 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) ### v0.2.3 (2020-05-24)

View File

@ -146,6 +146,8 @@ the request using environment variables:
| REMOTE_ADDR | Client IP address. | ``10.10.0.2`` | | REMOTE_ADDR | Client IP address. | ``10.10.0.2`` |
| REMOTE_HOST | Client IP address (alias for REMOTE_ADDR). | ``10.10.0.2`` | | REMOTE_HOST | Client IP address (alias for REMOTE_ADDR). | ``10.10.0.2`` |
| SERVER_PORT | Server port number. | ``1965`` | | 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: 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_NOT_AFTER | Certificate expiration date. | ``2021-04-05T04:18:22Z`` |
| TLS_CLIENT_SERIAL_NUMBER | Certificate serial number. | ``73629018972631`` | | TLS_CLIENT_SERIAL_NUMBER | Certificate serial number. | ``73629018972631`` |
| TLS_CLIENT_VERIFIED | Was the certificate verified by OpenSSL? | ``0`` (verified) / ``1`` (not verified) | | 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. 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 This includes the status code and meta string on the first line, and the

View File

@ -129,6 +129,7 @@ class GeminiProtocol(LineOnlyReceiver):
The TLS variable names borrow from the GLV-1.12556 server. The TLS variable names borrow from the GLV-1.12556 server.
""" """
url_parts = urllib.parse.urlparse(self.url) url_parts = urllib.parse.urlparse(self.url)
conn = self.transport.getHandle()
environ = { environ = {
"GEMINI_URL": self.url, "GEMINI_URL": self.url,
"HOSTNAME": self.server.hostname, "HOSTNAME": self.server.hostname,
@ -139,6 +140,8 @@ class GeminiProtocol(LineOnlyReceiver):
"SERVER_PORT": str(self.client_addr.port), "SERVER_PORT": str(self.client_addr.port),
"SERVER_PROTOCOL": "GEMINI", "SERVER_PROTOCOL": "GEMINI",
"SERVER_SOFTWARE": f"jetforce/{__version__}", "SERVER_SOFTWARE": f"jetforce/{__version__}",
"TLS_CIPHER": conn.get_cipher_name(),
"TLS_VERSION": conn.get_protocol_version_name(),
"client_certificate": None, "client_certificate": None,
} }
@ -146,7 +149,6 @@ class GeminiProtocol(LineOnlyReceiver):
if cert: if cert:
x509_cert = cert.to_cryptography() x509_cert = cert.to_cryptography()
cert_data = inspect_certificate(x509_cert) cert_data = inspect_certificate(x509_cert)
conn = self.transport.getHandle()
environ.update( environ.update(
{ {
"client_certificate": x509_cert, "client_certificate": x509_cert,
@ -158,8 +160,6 @@ class GeminiProtocol(LineOnlyReceiver):
"TLS_CLIENT_SERIAL_NUMBER": cert_data["serial_number"], "TLS_CLIENT_SERIAL_NUMBER": cert_data["serial_number"],
# Grab the value that was stashed during the TLS handshake # Grab the value that was stashed during the TLS handshake
"TLS_CLIENT_VERIFIED": getattr(conn, "verified", False), "TLS_CLIENT_VERIFIED": getattr(conn, "verified", False),
"TLS_CIPHER": conn.get_cipher_name(),
"TLS_VERSION": conn.get_protocol_version_name(),
} }
) )
return environ return environ