Skip to content

Instantly share code, notes, and snippets.

@andrewshadura
Created June 3, 2020 15:56
Show Gist options
  • Save andrewshadura/feb798effa21a23face4f07a6214f925 to your computer and use it in GitHub Desktop.
Save andrewshadura/feb798effa21a23face4f07a6214f925 to your computer and use it in GitHub Desktop.
eID signer launcher protocol
#!/usr/bin/env python3
import asyncio
from functools import partial
from pathlib import Path
import os
import ssl
import subprocess
import sys
from urllib.parse import urlparse, parse_qs, urlunparse
from uuid import uuid4
import websockets
from jsonrpc import JSONRPCResponseManager, Dispatcher
from jsonrpc.jsonrpc import JSONRPCRequest, JSONRPC20Request
# export DLAUNCHER_BIND_IP='127.0.0.1'
# export DLAUNCHER_CA_FILE='/home/$USER/.ditec/dlauncher/certificates/ca.crt'
# export DLAUNCHER_P12_FILE='/home/$USER/.ditec/dlauncher/certificates/dlauncher.ditec.sk.p12'
# export DLAUNCHER_P12_PASSWORD='heslo'
# export DLAUNCHER_URL='wss://127.0.0.1:8765/slave/f62fb1aa-0ff5-4b90-9823-2311e93225fe'
async def geturl_server(websocket, path, url, token):
if path == '/getUrl/%s' % token:
msg = JSONRPC20Request(method='hello', params={'url': url}).json
print(f"< {msg}")
await websocket.send(msg)
try:
await websocket.recv()
except websockets.exceptions.ConnectionClosed:
pass
primary = None
secondary = None
async def control_server(websocket, path):
global primary
global secondary
async def launch(url: str):
primary = websocket
print(f"launching {url}")
launchUrl(url)
while secondary is None:
await asyncio.sleep(1)
await websocket.recv()
try:
if path.startswith('/master/'):
primary = websocket
msg = JSONRPC20Request(method='hello', params={'version': '1.1.0.0'}).json
await websocket.send(msg)
async for message in websocket:
print(f"{path} > {message}")
m = JSONRPCRequest.from_json(message)
if m.method == 'dlauncher.launch':
await launch(m.params['url'])
else:
secondary = websocket
async for message in websocket:
print(f"{path} => {message} => master")
await primary.send(message)
except websockets.exceptions.ConnectionClosed:
pass
def prepare_ssl() -> ssl.SSLContext:
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
cert = Path(f"{os.environ['HOME']}/.ditec/dlauncher/certificates/dlauncher.ditec.sk.crt.pem")
ssl_context.load_cert_chain(cert, keyfile=cert.with_name('dlauncher.ditec.sk.key.pem'))
return ssl_context
localport = 8765
def main():
uri = urlparse(sys.argv[1])
if uri.scheme != 'ditec-dlauncher':
print('scheme has to be ditec-dlauncher')
sys.exit(1)
params = parse_qs(uri.query)
print(params)
ports = [int(p) for p in ','.join(params['ports']).split(',')]
print(ports)
# sys.exit(1)
ssl_context = prepare_ssl()
url = urlunparse(('wss', "%s:%d" % (params['hostnames'][0], localport), '/master/%s' % uuid4(), None, None, None))
token = params['token'][0]
handler = partial(geturl_server, url=url, token=token)
loop = asyncio.get_event_loop()
tasks = [websockets.serve(handler, "127.0.0.1", port, ssl=ssl_context) for port in ports]
control_task = websockets.serve(control_server, "127.0.0.1", localport, ssl=ssl_context)
loop.run_until_complete(asyncio.gather(*tasks, control_task, loop=loop, return_exceptions=True))
loop.run_forever()
def launchUrl(url: str):
os.environ['DLAUNCHER_BIND_IP'] = '127.0.0.1'
os.environ['DLAUNCHER_CA_FILE'] = f'{os.environ["HOME"]}/.ditec/dlauncher/certificates/ca.crt'
os.environ['DLAUNCHER_P12_FILE'] = f'{os.environ["HOME"]}/.ditec/dlauncher/certificates/dlauncher.ditec.sk.p12'
os.environ['DLAUNCHER_P12_PASSWORD'] = 'heslo'
os.environ['DLAUNCHER_URL'] = 'wss://127.0.0.1:%d/slave/%s' % (localport, uuid4())
subprocess.Popen(["javaws", url], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
if __name__ == '__main__':
main()
#!/usr/bin/env python3
# WS client example
import asyncio
import websockets
import ssl
ctx = ssl._create_unverified_context()
async def sign():
uri = "wss://127.0.0.1:36489/4ff83b1e-9778-4602-8e6c-7a8240ee7553"
async with websockets.connect(uri, ssl=ctx) as websocket:
for i in range(1, 4):
msg = open('msg%d' % i, 'rt').read()
await websocket.send(msg)
print(f"> {msg:128}")
result = await websocket.recv()
print(f"< {result}")
async def getUrl():
uri = 'wss://127.0.0.1:64565/getUrl/c3649670-8529-08a0-91d8-4e9f7dab9540'
async with websockets.connect(uri, ssl=ctx) as websocket:
result = await websocket.recv()
print(f"< {result}")
async def launch():
uri = "wss://127.0.0.1:33549/master/9c596f62-3d56-411f-8dab-28b709e8a7df"
async with websockets.connect(uri, ssl=ctx) as websocket:
msg = '{"jsonrpc":"2.0","id":null,"method":"dlauncher.launch","params":{"url":"https://www.slovensko.sk/static/zep/java_apps/dsigner_dlauncher_2.0.jnlp"}}'
await websocket.send(msg)
async for message in websocket:
print(f"< {message}")
# asyncio.get_event_loop().run_until_complete(getUrl())
asyncio.get_event_loop().run_until_complete(launch())
# asyncio.get_event_loop().run_until_complete(sign())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment