This repository was archived by the owner on Nov 21, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathprovider.py
More file actions
134 lines (109 loc) · 5.01 KB
/
Copy pathprovider.py
File metadata and controls
134 lines (109 loc) · 5.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#!/usr/bin/env python
import asyncio
from curses import raw
from genericpath import isfile
import os, sys
from uvicorn.protocols.websockets.wsproto_impl import WSProtocol
import wsproto
from datetime import datetime
import json
import pathlib
import socket
from OpenSSL import SSL
import logging
from cryptography import x509
from cryptography.hazmat.primitives._serialization import Encoding
import aioopenssl
from wsproto import ConnectionType, WSConnection
from wsproto.events import (
AcceptConnection,
CloseConnection,
Message,
Ping,
Request,
TextMessage,
)
from pyeebus import x509_utils
logging.basicConfig(
format="%(message)s",
level=logging.DEBUG,
)
PROVIDER_PRIVATE_KEY_FN = os.getenv('PROVIDER_PRIVATE_KEY_FN', 'provider.key')
PROVIDER_PUBLIC_KEY_FN = os.getenv('PROVIDER_PUBLIC_KEY_FN', 'provider.pem')
PROVIDER_CERT_FN = os.getenv('PROVIDER_CERT_FN', 'provider.crt')
WEBSOCKET_HOST = os.getenv('WEBSOCKET_HOST', '127.0.0.1')
WEBSOCKET_PORT = int(os.getenv('WEBSOCKET_PORT', '8765'))
if not os.path.isfile(PROVIDER_PRIVATE_KEY_FN) and not os.path.isfile(PROVIDER_PUBLIC_KEY_FN) and not os.path.isfile(PROVIDER_CERT_FN):
print(f"generating public and private keys and certificate...")
x509_utils.generate_key(private_key_fn=PROVIDER_PRIVATE_KEY_FN, public_key_fn=PROVIDER_PUBLIC_KEY_FN)
x509_utils.generate_x509_keys_by_fn(public_key_pem_fn=PROVIDER_PUBLIC_KEY_FN, private_key_pem_fn=PROVIDER_PRIVATE_KEY_FN, cert_fn=PROVIDER_CERT_FN)
else:
print(f"One of the following files does exist already, thus, NOT creating any of those: {PROVIDER_PRIVATE_KEY_FN} {PROVIDER_PUBLIC_KEY_FN} {PROVIDER_CERT_FN}")
assert os.path.isfile(PROVIDER_PRIVATE_KEY_FN)
assert os.path.isfile(PROVIDER_PUBLIC_KEY_FN)
assert os.path.isfile(PROVIDER_CERT_FN)
connections = {}
"""
callback – The optional Python verification callback to use. This should take five arguments: A Connection object, an X509 object, and three integer variables, which are in turn potential error number, error depth and return code. callback should return True if verification passes and False otherwise. If omitted, OpenSSL’s default verification is used.
"""
def verify_cb(conn, cert, err, depth, ok):
print(cert)
x509_cert: x509.Certificate = cert.to_cryptography()
xx = x509_cert.public_bytes(encoding=Encoding.PEM)
print(xx)
ski = x509_cert.extensions.get_extension_for_oid(x509.oid.ExtensionOID.SUBJECT_KEY_IDENTIFIER)
# don't trust this for self-signed certs without recalculating it from pub key!!!
print(f"ski:{ski.value.digest}")
return 1 # TODO: security: 1 means cert check ok!
ssl_context = SSL.Context(SSL.SSLv23_METHOD)
ssl_context.set_cipher_list(b"TLS_AES_128_GCM_SHA256:AES128-GCM-SHA256") # do we need this?
ssl_context.set_verify(SSL.VERIFY_PEER, callback=verify_cb)
ssl_context.use_certificate_file(certfile=PROVIDER_CERT_FN)
ssl_context.use_privatekey_file(keyfile=PROVIDER_PRIVATE_KEY_FN)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
conn = SSL.Connection(ssl_context, sock)
sock.bind(('', WEBSOCKET_PORT))
sock.listen(5)
"""
while True:
# for every new connection, we get a new socket that we have to 'bind' to our ssl context
incoming_sock, fromaddr = sock.accept()
incoming_ssl_conn = SSL.Connection(ssl_context, incoming_sock)
incoming_ssl_conn.set_accept_state()
incoming_ssl_conn.do_handshake()
req = incoming_ssl_conn.read(4096)
print(req)
incoming_ssl_conn.write(b"HTTP/1.1 200 OK\r\nServer: my-special\r\nContent-length: 10\r\n\r\nHello!\r\n\r\n")
#incoming_ssl_conn.write(b"HTTP/1.1 200 OK\r\nContent-Length:20\r\nHelloWorld\r\n")
incoming_ssl_conn.set_shutdown(SSL.SENT_SHUTDOWN)
"""
def ssl_context_factory(xx):
return ssl_context
def handle_connection(transport: asyncio.Transport, reader_proto):
writer = asyncio.StreamWriter(transport=transport, protocol=reader_proto, reader=reader_proto.)
ws = WSConnection(ConnectionType.SERVER)
for event in ws.events():
if isinstance(event, Request):
print('Accepting connection request')
incoming_socket.send(ws.send(AcceptConnection()))
def stream_reader_proto_factory(loop):
reader = asyncio.StreamReader(loop=loop)
proto = asyncio.StreamReaderProtocol(reader)
return proto
loop = asyncio.get_event_loop()
while True:
incoming_sock, framaddr = sock.accept()
# our own SSL check
aiossl = aioopenssl.STARTTLSTransport(loop=asyncio.get_event_loop(), rawsock=incoming_sock, protocol=asyncio.Protocol(), ssl_context_factory=ssl_context_factory)
transport, reader_proto = aioopenssl.create_starttls_connection(
loop=loop,
protocol_factory=stream_reader_proto_factory,
use_starttls=False,
host=WEBSOCKET_HOST,
port=WEBSOCKET_PORT,
)
writer = asyncio.StreamWriter(transport=transport, protocol=reader_proto)
#incoming_ssl_conn = SSL.Connection(ssl_context, incoming_sock)
#incoming_ssl_conn.set_accept_state()
#incoming_ssl_conn.do_handshake()
handle_connection(transport, reader_proto)