diff options
| author | jwijenbergh <jeroenwijenbergh@protonmail.com> | 2022-03-15 16:12:48 +0100 |
|---|---|---|
| committer | jwijenbergh <jeroenwijenbergh@protonmail.com> | 2022-04-05 12:26:14 +0200 |
| commit | 5887d925486e7ce650c3440de6cd29dd2240e929 (patch) | |
| tree | 6bfce1ddb6a1de5647f23fe7131098ebb421034e /wrappers | |
| parent | a019e95fdbaea3d7af2d8ad10903fd656bfc4466 (diff) | |
Add callback state change and simplify wrappers
The python wrapper contained lots of code that should not be exposed.
The other wrappers I will update later
Diffstat (limited to 'wrappers')
| -rw-r--r-- | wrappers/python/eduvpncommon/__init__.py | 20 | ||||
| -rw-r--r-- | wrappers/python/eduvpncommon/auth.py | 14 | ||||
| -rw-r--r-- | wrappers/python/eduvpncommon/discovery.py | 86 | ||||
| -rw-r--r-- | wrappers/python/eduvpncommon/main.py | 22 |
4 files changed, 27 insertions, 115 deletions
diff --git a/wrappers/python/eduvpncommon/__init__.py b/wrappers/python/eduvpncommon/__init__.py index 911c671..c21f8d4 100644 --- a/wrappers/python/eduvpncommon/__init__.py +++ b/wrappers/python/eduvpncommon/__init__.py @@ -19,27 +19,17 @@ _libfile = f"{_lib_prefixes[_os]}{_libname}{_lib_suffixes[_os]}" # Library should have been copied to the lib/ folder lib = cdll.LoadLibrary(str(pathlib.Path(__file__).parent / "lib" / _libfile)) - -class GoSlice(Structure): - _fields_ = [("data", POINTER(c_char)), ("len", c_int64), ("cap", c_int64)] - - @staticmethod - def make(bs: bytes) -> "GoSlice": - return GoSlice((c_char * len(bs))(*bs), len(bs), len(bs)) # type: ignore - - +# Data types class DataError(Structure): _fields_ = [('data', c_void_p), ('error', c_int64)] +GOCB_StateChange = CFUNCTYPE(None, c_char_p, c_char_p) + +# Exposed functions +lib.Register.argtypes, lib.Register.restype = [c_char_p, c_char_p, GOCB_StateChange], None # We have to use c_void_p instead of c_char_p to free it properly # See https://stackoverflow.com/questions/13445568/python-ctypes-how-to-free-memory-getting-invalid-pointer-error -lib.Register.argtypes, lib.Register.restype = [c_char_p, c_char_p], None lib.InitializeOAuth.argtypes, lib.InitializeOAuth.restype = [], c_void_p -lib.GetOrganizationsList.argtypes, lib.GetOrganizationsList.restype = [], DataError -lib.GetServersList.argtypes, lib.GetServersList.restype = [], DataError lib.FreeString.argtypes, lib.FreeString.restype = [c_void_p], None -lib.Verify.argtypes, lib.Verify.restype = [GoSlice, GoSlice, GoSlice, c_uint64], c_int64 -lib.InsecureTestingSetExtraKey.argtypes, lib.InsecureTestingSetExtraKey.restype = [GoSlice], None - diff --git a/wrappers/python/eduvpncommon/auth.py b/wrappers/python/eduvpncommon/auth.py deleted file mode 100644 index b0d1410..0000000 --- a/wrappers/python/eduvpncommon/auth.py +++ /dev/null @@ -1,14 +0,0 @@ -from . import lib -from ctypes import * - -def Register(name, url): - name_bytes = name.encode('utf-8') - url_bytes = url.encode('utf-8') - lib.Register(name_bytes, url_bytes) - -def InitializeOAuth(): - ptr = lib.InitializeOAuth() - value = cast(ptr, c_char_p).value - authURL = value.decode() - lib.FreeString(ptr) - return authURL diff --git a/wrappers/python/eduvpncommon/discovery.py b/wrappers/python/eduvpncommon/discovery.py deleted file mode 100644 index 4820ca2..0000000 --- a/wrappers/python/eduvpncommon/discovery.py +++ /dev/null @@ -1,86 +0,0 @@ -from . import lib, GoSlice, DataError -from .error import GoError -from ctypes import * -from typing import Callable, List, Dict, Any -from enum import Enum -import json - -def getList(func: Callable) -> List[Dict[str, Any]]: - dataError = func() - ptr = dataError.data - error = dataError.error - body = "" - if not error: - body_value = cast(ptr, c_char_p).value - if body_value: - body = body_value.decode() - lib.FreeString(ptr) - if error: - raise RequestError(error) - - return json.loads(body) - -def GetOrganizationsList() -> List[Dict[str, Any]]: - return getList(lib.GetOrganizationsList) - -def GetServersList() -> List[Dict[str, Any]]: - return getList(lib.GetServersList) - - -class RequestErrorCode(Enum): - ErrRequestFileError = 1 # The request for the file has failed. - ErrVerifySigError = 2 # The signature failed to verify. - Unknown = -1 # Other unknown error. - -class RequestError(GoError): - def __init__(self, err: int): - super().__init__(RequestErrorCode(err), - { - RequestErrorCode.ErrRequestFileError: "file request error", - RequestErrorCode.ErrVerifySigError: "signature verify error", - RequestErrorCode.Unknown: "unknown error", - }) - - -class VerifyErrorCode(Enum): - ErrUnknownExpectedFileName = 1 # Unknown expected file name specified. The signature has not been verified. - ErrInvalidSignature = 2 # Signature is invalid (for the expected file type). - ErrInvalidSignatureUnknownKey = 3 # Signature was created with an unknown key and has not been verified. - ErrTooOld = 4 # Signature timestamp smaller than specified minimum signing time (rollback). - Unknown = -1 # Other unknown error. - -class VerifyError(GoError): - def __init__(self, err: int): - super().__init__(VerifyErrorCode(err), - { - VerifyErrorCode.ErrUnknownExpectedFileName: "unknown expected file name", - VerifyErrorCode.ErrInvalidSignature: "invalid signature", - VerifyErrorCode.ErrInvalidSignatureUnknownKey: "invalid signature (unknown key)", - VerifyErrorCode.ErrTooOld: "replay of previous signature (rollback)", - VerifyErrorCode.Unknown: "unknown error", - }) - - -def verify(signature: bytes, signed_json: bytes, expected_file_name: str, min_sign_time: int) -> None: - """ - Verifies the signature on the JSON server_list.json/organization_list.json file. - If the function returns, the signature is valid for the given file type. - - :param signature: .minisig signature file contents. - :param signed_json: Signed .json file contents. - :param expected_file_name: The file type to be verified, one of "server_list.json" or "organization_list.json". - :param min_sign_time: Minimum time for signature (UNIX timestamp, seconds). Should be set to at least the time of the previous signature. - - :raises VerifyException: If signature verification fails or expectedFileName is not one of the allowed values. - """ - - err = lib.Verify(GoSlice.make(signature), GoSlice.make(signed_json), - GoSlice.make(expected_file_name.encode()), min_sign_time) - if err: - raise VerifyError(err) - - -def _insecure_testing_set_extra_key(key_string: str) -> None: - """Use for testing only, see Go documentation.""" - - lib.InsecureTestingSetExtraKey(GoSlice.make(key_string.encode())) diff --git a/wrappers/python/eduvpncommon/main.py b/wrappers/python/eduvpncommon/main.py new file mode 100644 index 0000000..b8278ad --- /dev/null +++ b/wrappers/python/eduvpncommon/main.py @@ -0,0 +1,22 @@ +from . import lib, GOCB_StateChange +from ctypes import * + +@GOCB_StateChange +def state_change(old, new): + print(f"Python: State change {old.decode()} {new.decode()}") + +def InitializeOAuth(): + ptr = lib.InitializeOAuth() + value = cast(ptr, c_char_p).value + authURL = value.decode() + lib.FreeString(ptr) + return authURL + +# Registers the python app with the GO code +# name: The name of the app to be registered +# url: The url of the server to connect to, FIXME: To be removed +# state_callback: The callback to trigger whenever a state is changed, FIXME: Remove whenever this wrapper has implemented callbacks using function decorations +def Register(name, url, state_callback): + name_bytes = name.encode('utf-8') + url_bytes = url.encode('utf-8') + lib.Register(name_bytes, url_bytes, state_callback) |
