diff options
| -rw-r--r-- | exports/exports.go | 10 | ||||
| -rw-r--r-- | src/server.go | 5 | ||||
| -rw-r--r-- | src/state.go | 41 | ||||
| -rw-r--r-- | src/wireguard.go | 23 | ||||
| -rw-r--r-- | wrappers/python/eduvpncommon/__init__.py | 1 | ||||
| -rw-r--r-- | wrappers/python/eduvpncommon/main.py | 49 | ||||
| -rw-r--r-- | wrappers/python/main.py | 21 |
7 files changed, 127 insertions, 23 deletions
diff --git a/exports/exports.go b/exports/exports.go index 8236977..4e998bf 100644 --- a/exports/exports.go +++ b/exports/exports.go @@ -34,7 +34,8 @@ func StateCallback(old_state string, new_state string, data string) { //export Register func Register(name *C.char, config_directory *C.char, stateCallback C.PythonCB) *C.char { P_StateCallback = stateCallback - registerErr := eduvpn.Register(eduvpn.GetVPNState(), C.GoString(name), C.GoString(config_directory), StateCallback) + state := eduvpn.GetVPNState() + registerErr := state.Register(C.GoString(name), C.GoString(config_directory), StateCallback) return C.CString(ErrorToString(registerErr)) } @@ -46,6 +47,13 @@ func ErrorToString(error error) string { return error.Error() } +//export Connect +func Connect(url *C.char) (*C.char, *C.char) { + state := eduvpn.GetVPNState() + config, configErr := state.Connect(C.GoString(url)) + return C.CString(config), C.CString(ErrorToString(configErr)) +} + //export GetOrganizationsList func GetOrganizationsList() (*C.char, *C.char) { state := eduvpn.GetVPNState() diff --git a/src/server.go b/src/server.go index 627843f..0ef3965 100644 --- a/src/server.go +++ b/src/server.go @@ -34,6 +34,11 @@ func (server *Server) Initialize(url string) error { return nil } +// FIXME: Check validity of tokens +func (server *Server) IsAuthenticated() bool { + return server.OAuth != nil +} + func (server *Server) GetEndpoints() error { url := server.BaseURL + "/.well-known/vpn-user-portal" body, bodyErr := HTTPGet(url) diff --git a/src/state.go b/src/state.go index ea268ec..cd8fa19 100644 --- a/src/state.go +++ b/src/state.go @@ -2,8 +2,9 @@ package eduvpn type VPNState struct { // Info passed by the client - ConfigDirectory string `json:"-"` - Name string `json:"-"` + ConfigDirectory string `json:"-"` + Name string `json:"-"` + StateCallback func(string, string, string) `json:"-"` // The chosen server Server *Server `json:"server"` @@ -12,11 +13,12 @@ type VPNState struct { DiscoList *DiscoList `json:"disco"` } -func Register(state *VPNState, name string, directory string, stateCallback func(string, string, string)) error { +func (state *VPNState) Register(name string, directory string, stateCallback func(string, string, string)) error { state.Name = name state.ConfigDirectory = directory + state.StateCallback = stateCallback - stateCallback("START", "REGISTERED", "app registered") + state.StateCallback("Start", "Registered", "app registered") // Try to load the previous configuration if state.LoadConfig() != nil { @@ -26,6 +28,37 @@ func Register(state *VPNState, name string, directory string, stateCallback func return nil } +func (state *VPNState) Connect(url string) (string, error) { + if state.Server == nil { + state.Server = &Server{} + } + initializeErr := state.Server.Initialize(url) + + if initializeErr != nil { + return "", initializeErr + } + + if !state.Server.IsAuthenticated() { + authURL, authInitializeErr := state.InitializeOAuth() + + if authInitializeErr != nil { + return "", authInitializeErr + } + + state.StateCallback("Registered", "OAuthInitialized", authURL) + oauthErr := state.FinishOAuth() + + if oauthErr != nil { + return "", oauthErr + } + + state.StateCallback("OAuthInitialized", "OAuthFinished", "finished oauth") + state.WriteConfig() + } + + return state.WireguardGetConfig() +} + var VPNStateInstance *VPNState func GetVPNState() *VPNState { diff --git a/src/wireguard.go b/src/wireguard.go index 9441c51..0d5967c 100644 --- a/src/wireguard.go +++ b/src/wireguard.go @@ -6,13 +6,13 @@ import ( "regexp" ) -func WireguardGenerateKey() (wgtypes.Key, error) { +func wireguardGenerateKey() (wgtypes.Key, error) { key, error := wgtypes.GeneratePrivateKey() return key, error } // FIXME: Instead of doing a regex replace, decide if we should use a parser -func WireguardConfigAddKey(config string, key wgtypes.Key) string { +func wireguardConfigAddKey(config string, key wgtypes.Key) string { interface_section := "[Interface]" interface_section_escaped := regexp.QuoteMeta(interface_section) @@ -24,3 +24,22 @@ func WireguardConfigAddKey(config string, key wgtypes.Key) string { to_replace := fmt.Sprintf("%s\nPrivateKey = %s", interface_section, key.String()) return interface_re.ReplaceAllString(config, to_replace) } + +func (eduvpn *VPNState) WireguardGetConfig() (string, error) { + wireguardKey, wireguardErr := wireguardGenerateKey() + + if wireguardErr != nil { + return "", wireguardErr + } + + wireguardPublicKey := wireguardKey.PublicKey().String() + configWireguard, configErr := eduvpn.APIConnectWireguard(wireguardPublicKey) + + if configErr != nil { + return "", configErr + } + + configWireguardKey := wireguardConfigAddKey(configWireguard, wireguardKey) + + return configWireguardKey, nil +} diff --git a/wrappers/python/eduvpncommon/__init__.py b/wrappers/python/eduvpncommon/__init__.py index 073af39..faa311d 100644 --- a/wrappers/python/eduvpncommon/__init__.py +++ b/wrappers/python/eduvpncommon/__init__.py @@ -33,6 +33,7 @@ class DataError(Structure): VPNStateChange = CFUNCTYPE(None, c_char_p, c_char_p, c_char_p) # Exposed functions +lib.Connect.argtypes, lib.Connect.restype = [c_char_p], DataError lib.Register.argtypes, lib.Register.restype = [c_char_p, c_char_p, VPNStateChange], None lib.GetOrganizationsList.argtypes, lib.GetOrganizationsList.restype = [], DataError lib.GetServersList.argtypes, lib.GetServersList.restype = [], DataError diff --git a/wrappers/python/eduvpncommon/main.py b/wrappers/python/eduvpncommon/main.py index 9a4931f..9e1f25e 100644 --- a/wrappers/python/eduvpncommon/main.py +++ b/wrappers/python/eduvpncommon/main.py @@ -1,12 +1,13 @@ from . import lib, VPNStateChange, GetDataError, GetPtrString from ctypes import * from enum import Enum -import functools + class StateType(Enum): Enter = 1 Leave = 2 + # 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 @@ -19,19 +20,46 @@ def Register(name, config_directory, state_callback): return err_string +def GetDiscoServers(): + servers, serversErr = GetDataError(lib.GetServersList()) + organizations, organizationsErr = GetDataError(lib.GetOrganizationsList()) + return servers, serversErr, organizations, organizationsErr + + +def Connect(url): + url_bytes = url.encode("utf-8") + data_error = lib.Connect(url_bytes) + return GetDataError(data_error) + + +# This has to be global as otherwise the callback is not alive +callback_function = None + + +def register_callback(eduvpn): + global callback_function + callback_function = VPNStateChange( + lambda old_state, new_state, data: eduvpn.callback( + old_state.decode(), new_state.decode(), data.decode() + ) + ) + + class EduVPN(object): def __init__(self, name, config_directory): self.event_handler = EventHandler() self.name = name self.config_directory = config_directory + register_callback(self) def register(self) -> bool: - closure = VPNStateChange( - lambda old_state, new_state, data: self.callback( - old_state.decode(), new_state.decode(), data.decode() - ) - ) - return Register(self.name, self.config_directory, closure) == "" + return Register(self.name, self.config_directory, callback_function) == "" + + def get_disco(self): + return GetDiscoServers() + + def connect(self, url): + return Connect(url) @property def event(self): @@ -51,6 +79,7 @@ class EventHandler(object): self.handlers[(state, state_type)] = [] self.handlers[(state, state_type)].append(func) return func + return wrapped_f def run_state(self, state, state_type, data): @@ -64,9 +93,3 @@ class EventHandler(object): return self.run_state(old_state, StateType.Leave, data) self.run_state(new_state, StateType.Enter, data) - - -def GetDiscoServers(): - servers, serversErr = GetDataError(lib.GetServersList()) - organizations, organizationsErr = GetDataError(lib.GetOrganizationsList()) - return servers, serversErr, organizations, organizationsErr diff --git a/wrappers/python/main.py b/wrappers/python/main.py index a248b71..6bd7d86 100644 --- a/wrappers/python/main.py +++ b/wrappers/python/main.py @@ -1,12 +1,27 @@ import eduvpncommon.main as eduvpn +import webbrowser _eduvpn = eduvpn.EduVPN("org.eduvpn.app.linux", "configs") -@_eduvpn.event.on("REGISTERED", eduvpn.StateType.Enter) -def registered(data): - print(f"REGISTERED PYTHON WITH DATA {data}") +@_eduvpn.event.on("OAuthInitialized", eduvpn.StateType.Enter) +def oauth_initialized(url): + print(f"Got OAUTH url {url}") + webbrowser.open(url) + + +@_eduvpn.event.on("OAuthFinished", eduvpn.StateType.Enter) +def oauth_finished(data): + print(f"Oauth finished {data}") _eduvpn.register() +print(_eduvpn.get_disco()) + +config, error = _eduvpn.connect("https://eduvpn.jwijenbergh.com") +# +if error != "": + print("Got connect error", error) + +print(config) |
