summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjwijenbergh <jeroenwijenbergh@protonmail.com>2022-03-23 18:15:13 +0100
committerjwijenbergh <jeroenwijenbergh@protonmail.com>2022-03-23 18:15:13 +0100
commit40053552852cf8c27fe7658b64df001d65b0a65e (patch)
tree6f48e819eaec926c894af6d6225ea6d8b36de657
parentf1e5096b7827d82ab5b2df10080a2ad9223f2665 (diff)
Add getting profiles and add openvpn config support
-rw-r--r--src/api.go56
-rw-r--r--src/oauth.go7
-rw-r--r--src/openvpn.go11
-rw-r--r--src/server.go63
-rw-r--r--src/state.go2
-rw-r--r--src/wireguard.go4
6 files changed, 125 insertions, 18 deletions
diff --git a/src/api.go b/src/api.go
index 5e11afd..cc84989 100644
--- a/src/api.go
+++ b/src/api.go
@@ -2,27 +2,28 @@ package eduvpn
import (
"fmt"
+ "encoding/json"
"net/http"
"net/url"
)
// Authenticated wrappers on top of HTTP
-func (eduvpn *VPNState) apiAuthenticatedWithOpts(method string, endpoint string, opts *HTTPOptionalParams) (http.Header, []byte, error) {
+func (server *Server) apiAuthenticatedWithOpts(method string, endpoint string, opts *HTTPOptionalParams) (http.Header, []byte, error) {
// Ensure optional is not nil as we will fill it with headers
if opts == nil {
opts = &HTTPOptionalParams{}
}
- url := eduvpn.Server.Endpoints.API.V3.API + endpoint
+ url := server.Endpoints.API.V3.API + endpoint
// Ensure we have non-expired tokens
- oauthErr := eduvpn.EnsureTokensOAuth()
+ oauthErr := server.OAuth.EnsureTokens()
if oauthErr != nil {
return nil, nil, oauthErr
}
headerKey := "Authorization"
- headerValue := fmt.Sprintf("Bearer %s", eduvpn.Server.OAuth.Token.Access)
+ headerValue := fmt.Sprintf("Bearer %s", server.OAuth.Token.Access)
if opts.Headers != nil {
opts.Headers.Add(headerKey, headerValue)
} else {
@@ -35,7 +36,26 @@ func (eduvpn *VPNState) apiAuthenticatedWithOpts(method string, endpoint string,
return header, body, nil
}
-func (eduvpn *VPNState) APIConnectWireguard(pubkey string) (string, string, error) {
+func (server *Server) APIInfo() error {
+ _, body, bodyErr := server.apiAuthenticatedWithOpts(http.MethodGet, "/info", nil)
+ if bodyErr != nil {
+ return bodyErr
+ }
+ structure := &ServerProfileInfo{}
+ jsonErr := json.Unmarshal(body, structure)
+
+ if jsonErr != nil {
+ return jsonErr
+ }
+
+ server.Profiles = structure
+
+ // FIXME: Implement profile selection callback
+ server.Profiles.Current = 0
+ return nil
+}
+
+func (server *Server) APIConnectWireguard(profile_id string, pubkey string) (string, string, error) {
headers := &http.Header{
"content-type": {"application/x-www-form-urlencoded"},
"accept": {"application/x-wireguard-profile"},
@@ -45,11 +65,29 @@ func (eduvpn *VPNState) APIConnectWireguard(pubkey string) (string, string, erro
"profile_id": {"default"},
"public_key": {pubkey},
}
- header, body, bodyErr := eduvpn.apiAuthenticatedWithOpts(http.MethodPost, "/connect", &HTTPOptionalParams{Headers: headers, Body: urlForm})
- if bodyErr != nil {
- return "", "", bodyErr
+ header, connectBody, connectErr := server.apiAuthenticatedWithOpts(http.MethodPost, "/connect", &HTTPOptionalParams{Headers: headers, Body: urlForm})
+ if connectErr != nil {
+ return "", "", connectErr
+ }
+
+ expires := header.Get("expires")
+ return string(connectBody), expires, nil
+}
+
+func (server *Server) APIConnectOpenVPN(profile_id string) (string, string, error) {
+ headers := &http.Header{
+ "content-type": {"application/x-www-form-urlencoded"},
+ "accept": {"application/x-openvpn-profile"},
+ }
+
+ urlForm := url.Values{
+ "profile_id": {"default"},
+ }
+ header, connectBody, connectErr := server.apiAuthenticatedWithOpts(http.MethodPost, "/connect", &HTTPOptionalParams{Headers: headers, Body: urlForm})
+ if connectErr != nil {
+ return "", "", connectErr
}
expires := header.Get("expires")
- return string(body), expires, nil
+ return string(connectBody), expires, nil
}
diff --git a/src/oauth.go b/src/oauth.go
index f0d5b4a..291a409 100644
--- a/src/oauth.go
+++ b/src/oauth.go
@@ -269,12 +269,7 @@ func (eduvpn *VPNState) FinishOAuth() error {
return oauth.getTokensWithCallback()
}
-func (eduvpn *VPNState) EnsureTokensOAuth() error {
- oauth := eduvpn.Server.OAuth
- if oauth == nil {
- panic("invalid oauth state")
- }
-
+func (oauth *OAuth) EnsureTokens() error {
if oauth.isTokensExpired() {
return oauth.getTokensWithRefresh()
}
diff --git a/src/openvpn.go b/src/openvpn.go
new file mode 100644
index 0000000..2cab2c4
--- /dev/null
+++ b/src/openvpn.go
@@ -0,0 +1,11 @@
+package eduvpn
+
+func (server *Server) OpenVPNGetConfig() (string, error) {
+ configOpenVPN, _, configErr := server.APIConnectOpenVPN("default")
+
+ if configErr != nil {
+ return "", configErr
+ }
+
+ return configOpenVPN, nil
+}
diff --git a/src/server.go b/src/server.go
index 8f8706e..1dc0f88 100644
--- a/src/server.go
+++ b/src/server.go
@@ -1,6 +1,7 @@
package eduvpn
import (
+ "errors"
"encoding/json"
)
@@ -8,6 +9,21 @@ type Server struct {
BaseURL string `json:"base_url"`
Endpoints *ServerEndpoints `json:"endpoints"`
OAuth *OAuth `json:"oauth"`
+ Profiles *ServerProfileInfo `json:"profiles"`
+}
+
+type ServerProfile struct {
+ ID string `json:"profile_id"`
+ DisplayName string `json:"display_name"`
+ VPNProtoList []string `json:"vpn_proto_list"`
+ DefaultGateway bool `json:"default_gateway"`
+}
+
+type ServerProfileInfo struct {
+ Current uint8 `json:"current_profile"`
+ Info struct {
+ ProfileList []ServerProfile `json:"profile_list"`
+ } `json:"info"`
}
type ServerEndpointList struct {
@@ -58,3 +74,50 @@ func (server *Server) GetEndpoints() error {
return nil
}
+
+func (profiles *ServerProfileInfo) getCurrentProfile() (*ServerProfile, error) {
+ if profiles.Info.ProfileList == nil {
+ return nil, errors.New("No server profiles")
+ }
+
+ if (int)(profiles.Current) >= len(profiles.Info.ProfileList) {
+ return nil, errors.New("Invalid profile")
+ }
+ return &profiles.Info.ProfileList[profiles.Current], nil
+}
+
+func (profile *ServerProfile) supportsWireguard() bool {
+ for _, proto := range profile.VPNProtoList {
+ if proto == "wireguard" {
+ return true
+ }
+ }
+ return false
+}
+
+func (server *Server) GetCurrentProfile() (*ServerProfile, error) {
+ if server.Profiles == nil {
+ return nil, errors.New("No server profiles found")
+ }
+
+ return server.Profiles.getCurrentProfile()
+}
+
+func (server *Server) GetConfig() (string, error) {
+ infoErr := server.APIInfo()
+
+ if infoErr != nil {
+ return "", infoErr
+ }
+
+ profile, profileErr := server.GetCurrentProfile()
+
+ if profileErr != nil {
+ return "", profileErr
+ }
+
+ if profile.supportsWireguard() {
+ return server.WireguardGetConfig()
+ }
+ return server.OpenVPNGetConfig()
+}
diff --git a/src/state.go b/src/state.go
index cd8fa19..ab4f3fc 100644
--- a/src/state.go
+++ b/src/state.go
@@ -56,7 +56,7 @@ func (state *VPNState) Connect(url string) (string, error) {
state.WriteConfig()
}
- return state.WireguardGetConfig()
+ return state.Server.GetConfig()
}
var VPNStateInstance *VPNState
diff --git a/src/wireguard.go b/src/wireguard.go
index 5491764..96e7547 100644
--- a/src/wireguard.go
+++ b/src/wireguard.go
@@ -25,7 +25,7 @@ func wireguardConfigAddKey(config string, key wgtypes.Key) string {
return interface_re.ReplaceAllString(config, to_replace)
}
-func (eduvpn *VPNState) WireguardGetConfig() (string, error) {
+func (server *Server) WireguardGetConfig() (string, error) {
wireguardKey, wireguardErr := wireguardGenerateKey()
if wireguardErr != nil {
@@ -33,7 +33,7 @@ func (eduvpn *VPNState) WireguardGetConfig() (string, error) {
}
wireguardPublicKey := wireguardKey.PublicKey().String()
- configWireguard, _, configErr := eduvpn.APIConnectWireguard(wireguardPublicKey)
+ configWireguard, _, configErr := server.APIConnectWireguard("default", wireguardPublicKey)
if configErr != nil {
return "", configErr