pyOpenSSL + SocketServer WIP
This commit is contained in:
parent
7996b49792
commit
ef4023bd5c
45
jetforce.py
45
jetforce.py
|
@ -44,7 +44,6 @@ import pathlib
|
||||||
import re
|
import re
|
||||||
import socket
|
import socket
|
||||||
import socketserver
|
import socketserver
|
||||||
import ssl
|
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
|
@ -56,6 +55,7 @@ from cryptography import x509
|
||||||
from cryptography.hazmat.backends import default_backend
|
from cryptography.hazmat.backends import default_backend
|
||||||
from cryptography.hazmat.primitives import hashes, serialization
|
from cryptography.hazmat.primitives import hashes, serialization
|
||||||
from cryptography.hazmat.primitives.asymmetric import rsa
|
from cryptography.hazmat.primitives.asymmetric import rsa
|
||||||
|
from OpenSSL import SSL
|
||||||
|
|
||||||
if sys.version_info < (3, 7):
|
if sys.version_info < (3, 7):
|
||||||
sys.exit("Fatal Error: jetforce requires Python 3.7+")
|
sys.exit("Fatal Error: jetforce requires Python 3.7+")
|
||||||
|
@ -693,7 +693,7 @@ class GeminiServer(socketserver.ThreadingTCPServer):
|
||||||
app: typing.Callable,
|
app: typing.Callable,
|
||||||
host: str = "127.0.0.1",
|
host: str = "127.0.0.1",
|
||||||
port: int = 1965,
|
port: int = 1965,
|
||||||
ssl_context: ssl.SSLContext = None,
|
ssl_context: SSL.Context = None,
|
||||||
hostname: str = "localhost",
|
hostname: str = "localhost",
|
||||||
) -> None:
|
) -> None:
|
||||||
|
|
||||||
|
@ -723,16 +723,14 @@ class GeminiServer(socketserver.ThreadingTCPServer):
|
||||||
|
|
||||||
self.serve_forever()
|
self.serve_forever()
|
||||||
|
|
||||||
def get_request(self):
|
def get_request(self) -> typing.Tuple[SSL.Connection, typing.Tuple[str, int]]:
|
||||||
"""
|
"""
|
||||||
Wrap the incoming request in an SSL connection.
|
Wrap the incoming request in an SSL connection.
|
||||||
"""
|
"""
|
||||||
# noinspection PyTupleAssignmentBalance
|
# noinspection PyTupleAssignmentBalance
|
||||||
sock, client_addr = super(GeminiServer, self).get_request()
|
sock, client_addr = super(GeminiServer, self).get_request()
|
||||||
ssl_sock = self.ssl_context.wrap_socket(
|
sock = SSL.Connection(self.ssl_context, sock)
|
||||||
sock, server_side=True, do_handshake_on_connect=False
|
return sock, client_addr
|
||||||
)
|
|
||||||
return ssl_sock, client_addr
|
|
||||||
|
|
||||||
def log_message(self, message: str) -> None:
|
def log_message(self, message: str) -> None:
|
||||||
"""
|
"""
|
||||||
|
@ -790,36 +788,25 @@ def make_ssl_context(
|
||||||
keyfile: typing.Optional[str] = None,
|
keyfile: typing.Optional[str] = None,
|
||||||
cafile: typing.Optional[str] = None,
|
cafile: typing.Optional[str] = None,
|
||||||
capath: typing.Optional[str] = None,
|
capath: typing.Optional[str] = None,
|
||||||
) -> ssl.SSLContext:
|
) -> SSL.Context:
|
||||||
"""
|
"""
|
||||||
Generate a sane default SSL context for a Gemini server.
|
Generate a sane default SSL context for a Gemini server.
|
||||||
|
|
||||||
For more information on what these variables mean and what values they can
|
|
||||||
contain, see the python standard library documentation:
|
|
||||||
|
|
||||||
https://docs.python.org/3/library/ssl.html#ssl-contexts
|
|
||||||
|
|
||||||
verify_mode: ssl.CERT_OPTIONAL
|
|
||||||
A client certificate request is sent to the client. The client may
|
|
||||||
either ignore the request or send a certificate in order perform TLS
|
|
||||||
client cert authentication. If the client chooses to send a certificate,
|
|
||||||
it is verified. Any verification error immediately aborts the TLS
|
|
||||||
handshake.
|
|
||||||
"""
|
"""
|
||||||
if certfile is None:
|
if certfile is None:
|
||||||
certfile, keyfile = generate_ad_hoc_certificate(hostname)
|
certfile, keyfile = generate_ad_hoc_certificate(hostname)
|
||||||
|
|
||||||
context = ssl.SSLContext()
|
context = SSL.Context(SSL.TLSv1_2_METHOD)
|
||||||
context.verify_mode = ssl.CERT_OPTIONAL
|
context.use_certificate_file(certfile)
|
||||||
context.load_cert_chain(certfile, keyfile)
|
context.use_privatekey_file(keyfile or certfile)
|
||||||
|
context.check_privatekey()
|
||||||
if not cafile and not capath:
|
if cafile or capath:
|
||||||
# Load from the system's default client CA directory
|
|
||||||
context.load_default_certs(purpose=ssl.Purpose.CLIENT_AUTH)
|
|
||||||
else:
|
|
||||||
# Use a custom CA for validating client certificates
|
|
||||||
context.load_verify_locations(cafile, capath)
|
context.load_verify_locations(cafile, capath)
|
||||||
|
|
||||||
|
def verify_cb(connection, x509, err_no, err_depth, return_code):
|
||||||
|
pass
|
||||||
|
|
||||||
|
context.set_verify(SSL.VERIFY_PEER, verify_cb)
|
||||||
|
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue