GNServer 0.0.0.0.60__py3-none-any.whl → 0.0.0.0.61__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- GNServer/_app.py +34 -26
- GNServer/_client.py +2 -2
- GNServer/models.py +38 -29
- {gnserver-0.0.0.0.60.dist-info → gnserver-0.0.0.0.61.dist-info}/METADATA +1 -1
- {gnserver-0.0.0.0.60.dist-info → gnserver-0.0.0.0.61.dist-info}/RECORD +8 -8
- {gnserver-0.0.0.0.60.dist-info → gnserver-0.0.0.0.61.dist-info}/WHEEL +0 -0
- {gnserver-0.0.0.0.60.dist-info → gnserver-0.0.0.0.61.dist-info}/licenses/LICENSE +0 -0
- {gnserver-0.0.0.0.60.dist-info → gnserver-0.0.0.0.61.dist-info}/top_level.txt +0 -0
GNServer/_app.py
CHANGED
@@ -341,30 +341,7 @@ class App:
|
|
341
341
|
|
342
342
|
if not stream: # если не стрим, то ждем конец quic стрима и запускаем обработку ответа
|
343
343
|
if event.end_stream:
|
344
|
-
|
345
|
-
if self._api._kdc is not None:
|
346
|
-
buf, domain = self._api._kdc.decode(bytes(buf))
|
347
|
-
else:
|
348
|
-
domain = None
|
349
|
-
|
350
|
-
if buf is not None:
|
351
|
-
try:
|
352
|
-
request = GNRequest.deserialize(buf, mode)
|
353
|
-
if domain is not None:
|
354
|
-
request.client._data['domain'] = domain
|
355
|
-
except:
|
356
|
-
asyncio.create_task(self.sendRawResponse(stream_id, AllGNFastCommands.KDCDecryptRequestFailed().serialize(mode=mode)))
|
357
|
-
self._buffer.pop(event.stream_id, None)
|
358
|
-
return
|
359
|
-
|
360
|
-
else:
|
361
|
-
raise Exception('Не удалось расшифровать от KDC')
|
362
|
-
|
363
|
-
request.stream_id = stream_id # type: ignore
|
364
|
-
logger.debug(f'[<] Request: {request.method} {request.url}')
|
365
|
-
asyncio.create_task(self._handle_request(request, mode))
|
366
|
-
|
367
|
-
self._buffer.pop(event.stream_id, None)
|
344
|
+
asyncio.create_task(self._resolve_raw_request(stream_id, buf, mode))
|
368
345
|
return
|
369
346
|
|
370
347
|
# если стрим, то смотрим сколько пришло данных
|
@@ -380,6 +357,9 @@ class App:
|
|
380
357
|
del buf[:lenght]
|
381
358
|
|
382
359
|
# формируем запрос
|
360
|
+
|
361
|
+
asyncio.create_task(self.sendRawResponse(stream_id, AllGNFastCommands.NotImplemented().serialize(mode=mode)))
|
362
|
+
return
|
383
363
|
|
384
364
|
if self._api._kdc is not None:
|
385
365
|
data, domain = self._api._kdc.decode(data)
|
@@ -422,9 +402,37 @@ class App:
|
|
422
402
|
request._stream = w # type: ignore
|
423
403
|
asyncio.create_task(self._handle_request(request, mode))
|
424
404
|
|
425
|
-
async def
|
405
|
+
async def _resolve_raw_request(self, stream_id: int, data: bytes, mode: int):
|
406
|
+
|
407
|
+
if self._api._kdc is not None:
|
408
|
+
data, domain = await self._api._kdc.decode(bytes(data))
|
409
|
+
else:
|
410
|
+
domain = None
|
411
|
+
|
412
|
+
if data is None:
|
413
|
+
self._buffer.pop(stream_id, None)
|
414
|
+
raise Exception('Не удалось расшифровать от KDC')
|
415
|
+
|
416
|
+
try:
|
417
|
+
request = GNRequest.deserialize(data, mode)
|
418
|
+
if domain is not None:
|
419
|
+
request.client._data['domain'] = domain
|
420
|
+
except:
|
421
|
+
self._buffer.pop(stream_id, None)
|
422
|
+
await self.sendRawResponse(stream_id, AllGNFastCommands.KDCDecryptRequestFailed().serialize(mode=mode))
|
423
|
+
return
|
426
424
|
|
425
|
+
logger.debug(f'[<] Request: {request.method} {request.url}')
|
426
|
+
|
427
427
|
request.client._data['remote_addr'] = self._quic._network_paths[0].addr
|
428
|
+
request.stream_id = stream_id # type: ignore
|
429
|
+
|
430
|
+
self._buffer.pop(stream_id, None)
|
431
|
+
await self._handle_request(request, mode)
|
432
|
+
|
433
|
+
|
434
|
+
async def _handle_request(self, request: GNRequest, mode: int):
|
435
|
+
|
428
436
|
|
429
437
|
try:
|
430
438
|
response = await self._api.dispatchRequest(request)
|
@@ -465,7 +473,7 @@ class App:
|
|
465
473
|
|
466
474
|
|
467
475
|
if self._api._kdc is not None:
|
468
|
-
blob = self._api._kdc.encode(request.client.domain, blob)
|
476
|
+
blob = await self._api._kdc.encode(request.client.domain, blob)
|
469
477
|
|
470
478
|
await self.sendRawResponse(request.stream_id, blob=blob, end_stream=end_stream)
|
471
479
|
|
GNServer/_client.py
CHANGED
@@ -617,7 +617,7 @@ class RawQuicClient(QuicConnectionProtocol):
|
|
617
617
|
blob = request.serialize(_sys_s_mode)
|
618
618
|
|
619
619
|
if self.quicClient._client._kdc is not None:
|
620
|
-
blob = self.quicClient._client._kdc.encode(request.url.hostname, blob)
|
620
|
+
blob = await self.quicClient._client._kdc.encode(request.url.hostname, blob)
|
621
621
|
|
622
622
|
sid = self._quic.get_next_available_stream_id()
|
623
623
|
self._enqueue(sid, blob, True, False)
|
@@ -629,7 +629,7 @@ class RawQuicClient(QuicConnectionProtocol):
|
|
629
629
|
data = await fut
|
630
630
|
|
631
631
|
if self.quicClient._client._kdc is not None:
|
632
|
-
data, domain = self.quicClient._client._kdc.decode(data)
|
632
|
+
data, domain = await self.quicClient._client._kdc.decode(data)
|
633
633
|
|
634
634
|
if data is not None:
|
635
635
|
r = GNResponse.deserialize(data, _sys_s_mode)
|
GNServer/models.py
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
|
2
|
-
from typing import List, Optional, Dict
|
2
|
+
from typing import List, Optional, Dict, Union
|
3
3
|
from KeyisBTools.cryptography.sign import s2
|
4
4
|
from KeyisBTools.cryptography import m1
|
5
5
|
|
@@ -9,12 +9,13 @@ from gnobjects.net.objects import Url
|
|
9
9
|
from KeyisBTools.cryptography.bytes import hash3
|
10
10
|
|
11
11
|
class KDCObject:
|
12
|
-
def __init__(self, domain: str, kdc_domain: str, kdc_key: bytes, requested_domains: List[str]):
|
12
|
+
def __init__(self, domain: str, kdc_domain: str, kdc_key: bytes, requested_domains: List[str], active_key_synchronization: bool = True):
|
13
13
|
self._domain = domain
|
14
14
|
self._domain_hash = hash3(domain.encode())
|
15
15
|
self._kdc_domain = kdc_domain
|
16
16
|
self._kdc_key = kdc_key
|
17
17
|
self._requested_domains = requested_domains
|
18
|
+
self._active_key_synchronization = active_key_synchronization
|
18
19
|
|
19
20
|
from ._client import AsyncClient
|
20
21
|
self._client = AsyncClient(domain)
|
@@ -28,13 +29,6 @@ class KDCObject:
|
|
28
29
|
|
29
30
|
async def init(self, servers_keys: Optional[Dict[str, bytes]] = None): # type: ignore
|
30
31
|
|
31
|
-
if self._kdc_domain not in self._servers_keys:
|
32
|
-
self._servers_keys[self._kdc_domain] = self._kdc_key
|
33
|
-
h = hash3(self._kdc_domain.encode())
|
34
|
-
self._servers_keys_hash_domain[h] = self._kdc_domain
|
35
|
-
self._servers_keys_domain_hash[self._kdc_domain] = h
|
36
|
-
|
37
|
-
|
38
32
|
if servers_keys is not None:
|
39
33
|
for i in self._requested_domains:
|
40
34
|
if i in servers_keys:
|
@@ -43,39 +37,50 @@ class KDCObject:
|
|
43
37
|
servers_keys = {}
|
44
38
|
|
45
39
|
if len(self._requested_domains) > 0:
|
46
|
-
|
47
|
-
r = await self._client.request(GNRequest('GET', Url(f'gn://{self._kdc_domain}/api/sys/server/keys'), payload=payload))
|
48
|
-
|
49
|
-
if not r.command.ok:
|
50
|
-
print(f'ERROR: {r.command} {r.payload}')
|
51
|
-
raise r
|
52
|
-
|
53
|
-
if servers_keys is None:
|
54
|
-
print(f'ERROR: {r.command} {r.payload}')
|
55
|
-
raise r
|
56
|
-
|
57
|
-
servers_keys.update(r.payload)
|
58
|
-
|
59
|
-
|
60
|
-
self._servers_keys.update(servers_keys)
|
40
|
+
await self.requestKDC(self._requested_domains) # type: ignore
|
61
41
|
|
42
|
+
|
43
|
+
def _update(self):
|
62
44
|
for domain in self._servers_keys.keys():
|
63
45
|
h = hash3(domain.encode())
|
64
46
|
self._servers_keys_hash_domain[h] = domain
|
65
47
|
self._servers_keys_domain_hash[domain] = h
|
66
48
|
|
49
|
+
async def requestKDC(self, domain_or_hash: Union[str, bytes, List[Union[str, bytes]]]):
|
50
|
+
if self._kdc_domain not in self._servers_keys:
|
51
|
+
self._servers_keys[self._kdc_domain] = self._kdc_key
|
52
|
+
h = hash3(self._kdc_domain.encode())
|
53
|
+
self._servers_keys_hash_domain[h] = self._kdc_domain
|
54
|
+
self._servers_keys_domain_hash[self._kdc_domain] = h
|
67
55
|
|
68
56
|
|
57
|
+
if not isinstance(domain_or_hash, list):
|
58
|
+
domain_or_hash = [domain_or_hash]
|
59
|
+
|
60
|
+
r = await self._client.request(GNRequest('GET', Url(f'gn://{self._kdc_domain}/api/sys/server/keys'), payload=domain_or_hash))
|
69
61
|
|
70
|
-
|
62
|
+
|
63
|
+
if not r.command.ok:
|
64
|
+
print(f'ERROR: {r.command} {r.payload}')
|
65
|
+
raise r
|
66
|
+
|
67
|
+
self._servers_keys.update(r.payload)
|
68
|
+
self._update()
|
69
|
+
|
70
|
+
|
71
|
+
async def encode(self, domain: str, request: bytes):
|
71
72
|
if domain not in self._servers_keys:
|
72
|
-
|
73
|
+
if not self._active_key_synchronization:
|
74
|
+
return request
|
75
|
+
else:
|
76
|
+
await self.requestKDC(domain)
|
77
|
+
|
73
78
|
key = self._servers_keys[domain]
|
74
79
|
sig = s2.sign(key)
|
75
80
|
data = m1.encrypt(domain.encode(), sig, request[8:], key)
|
76
81
|
return request[:8] + sig + self._domain_hash + data
|
77
82
|
|
78
|
-
def decode(self, response: bytes):
|
83
|
+
async def decode(self, response: bytes):
|
79
84
|
r = response
|
80
85
|
if len(response) < 8+164+64:
|
81
86
|
return r, None
|
@@ -83,8 +88,12 @@ class KDCObject:
|
|
83
88
|
response = response[8:]
|
84
89
|
sig, domain_h, data = response[:164], response[164:164+64], response[164+64:]
|
85
90
|
if domain_h not in self._servers_keys_hash_domain:
|
86
|
-
|
87
|
-
|
91
|
+
if not self._active_key_synchronization:
|
92
|
+
print(domain_h, 'not in', self._servers_keys_hash_domain)
|
93
|
+
return r, None
|
94
|
+
else:
|
95
|
+
await self.requestKDC(domain_h)
|
96
|
+
|
88
97
|
d = self._servers_keys_hash_domain[domain_h]
|
89
98
|
key = self._servers_keys[d]
|
90
99
|
if not s2.verify(key, sig):
|
@@ -1,14 +1,14 @@
|
|
1
1
|
GNServer/__init__.py,sha256=QmvIIE5RWIv040_l216aWtYuiIPtLasdsFbH0Fya2SI,1793
|
2
|
-
GNServer/_app.py,sha256=
|
3
|
-
GNServer/_client.py,sha256=
|
2
|
+
GNServer/_app.py,sha256=VaQFxnIOC7xXnsbNP6UeknsJMLRAcqaNjrB1z7S8Oqg,19468
|
3
|
+
GNServer/_client.py,sha256=J8dkXBlehb23FVM9dq6OX5xUxpAGX_DWX5abD0SfFe0,32422
|
4
4
|
GNServer/_cors_resolver.py,sha256=aDxk4ItaEK-6vlDbkno8FJZEjczGEe8vkOui6_kz5-Y,5950
|
5
5
|
GNServer/_crt.py,sha256=SOmyX7zBiCY9EhVSekksQtBHgTIZVvdqNZ8Ni-E5Zow,1390
|
6
6
|
GNServer/_func_params_validation.py,sha256=pDXRzPVTdPnDHFMMmKd014SConBjFOuaLeJTY0vldlM,11412
|
7
7
|
GNServer/_routes.py,sha256=bJnmQ8uEhPVQgy2tTqE5TEIM8aFXV-lVI7c2nG0rQwk,3384
|
8
8
|
GNServer/_template_resolver.py,sha256=vdJYb_7PjIeTWq-Clr7jyj7QIvPBxplU7EqeOuMJ64c,1409
|
9
|
-
GNServer/models.py,sha256=
|
10
|
-
gnserver-0.0.0.0.
|
11
|
-
gnserver-0.0.0.0.
|
12
|
-
gnserver-0.0.0.0.
|
13
|
-
gnserver-0.0.0.0.
|
14
|
-
gnserver-0.0.0.0.
|
9
|
+
GNServer/models.py,sha256=OlXrV823qaeL2oClodC_AC2r5S9CCZeCN_t8-sMgs2Y,3781
|
10
|
+
gnserver-0.0.0.0.61.dist-info/licenses/LICENSE,sha256=_rN-sb3LemR3cKsEqjJRdXkdt7mME1mkW1BwWEn-zAw,1309
|
11
|
+
gnserver-0.0.0.0.61.dist-info/METADATA,sha256=gUzbJhdOIambAewKEY17QWX1pcMqdogsk2faorIQRmU,830
|
12
|
+
gnserver-0.0.0.0.61.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
13
|
+
gnserver-0.0.0.0.61.dist-info/top_level.txt,sha256=-UOUBuD4u7Qkb1o5PdcwyA3kx8xCH2lwy0tJHi26Wb4,9
|
14
|
+
gnserver-0.0.0.0.61.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|