summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjwijenbergh <jeroenwijenbergh@protonmail.com>2022-02-11 16:20:08 +0100
committerjwijenbergh <jeroenwijenbergh@protonmail.com>2022-04-05 12:26:11 +0200
commita1420bfd2bb4eb04006e46dfcf682ece86459749 (patch)
tree608d220aafb021fa372f576691c8f1bcedf07129
parent12a0a2700d64f99b8f14d03c8de1c1ea5e922eff (diff)
Abstract error types and remove JSON parsing
For now JSON parsing does not make a lot of sense. This is better off handled by the clients for now. Signed-off-by: jwijenbergh <jeroenwijenbergh@protonmail.com>
-rw-r--r--src/error.go30
-rw-r--r--src/server.go127
-rw-r--r--src/verify.go56
3 files changed, 98 insertions, 115 deletions
diff --git a/src/error.go b/src/error.go
new file mode 100644
index 0000000..87d7e53
--- /dev/null
+++ b/src/error.go
@@ -0,0 +1,30 @@
+package eduvpn
+
+type detailedVPNErrorCode int8
+type VPNErrorCode int8
+
+type VPNError struct {
+ Code VPNErrorCode
+ Detailed detailedVPNError
+}
+
+func (err VPNError) Error() string {
+ return err.Detailed.Error()
+}
+
+func (err VPNError) Unwrap() error {
+ return err.Detailed
+}
+
+type detailedVPNError struct {
+ Code detailedVPNErrorCode
+ Message string
+ Cause error
+}
+
+func (err detailedVPNError) Error() string {
+ return err.Message
+}
+func (err detailedVPNError) Unwrap() error {
+ return err.Cause
+}
diff --git a/src/server.go b/src/server.go
index 87b9672..37a8f62 100644
--- a/src/server.go
+++ b/src/server.go
@@ -1,82 +1,49 @@
package eduvpn
import (
- "encoding/json"
"io/ioutil"
"net/http"
"fmt"
)
-// Struct that defines the json format for
-// url: "https://disco.eduvpn.org/v2/organization_list.json"
-type organizations struct {
- V uint64 `json:"v"`
- OrganizationList []struct {
- DisplayName struct {
- En string `json:"en"`
- } `json:"display_name"`
- OrgId string `json:"org_id"`
- SecureInternetHome string `json:"secure_internet_home"`
- KeywordList struct {
- En string `json:"en"`
- } `json:"keyword_list"`
- } `json:"organization_list"`
-}
-
-// Struct that defines the json format for
-// url: "https://disco.eduvpn.org/v2/server_list.json"
-type servers struct {
- V uint64 `json:"v"`
- ServerList []struct {
- BaseUrl string `json:"base_url"`
- CountryCode string `json:"country_code"`
- PublicKeyList []string `json:"public_key_list"`
- ServerType string `json:"secure_internet"`
- SupportContact []string `json:"support_contact"`
- } `json:"server_list"`
-}
-
-func getFileUrl(url string) ([]byte, bool) {
+func getFileUrl(url string) ([]byte, error) {
// Do a Get request to the specified url
resp, reqErr := http.Get(url)
if reqErr != nil {
- fmt.Println("error making request")
- return nil, false
+ return nil, detailedVPNError{errRequestFileError, fmt.Sprintf("request failed for file url %s", url), reqErr}
}
// Close the response body at the end
defer resp.Body.Close()
// Check if http response code is ok
if resp.StatusCode != http.StatusOK {
- return nil, false
+ return nil, detailedVPNError{errRequestFileHTTPError, fmt.Sprintf("http status not ok for file url %s", url), nil}
}
// Read the body
body, readErr := ioutil.ReadAll(resp.Body)
if readErr != nil {
- fmt.Println("error reading body of request")
- return nil, false
+ return nil, detailedVPNError{errRequestFileReadError, fmt.Sprintf("error reading body from file url %s", url), readErr}
}
- return body, true
+ return body, nil
}
// Helper function that gets a disco json
// TODO: Verify signature
-func getDiscoJson(jsonFile string, structure interface{}) bool {
+func getDiscoFile(jsonFile string) ([]byte, error) {
// Get json data
fileUrl := "https://disco.eduvpn.org/v2/" + jsonFile
- fileBody, fileSuccess := getFileUrl(fileUrl)
+ fileBody, error := getFileUrl(fileUrl)
- if !fileSuccess {
- fmt.Println("error getting file")
+ if error != nil {
+ return nil, error
}
// Get signature
sigUrl := fileUrl + ".minisig"
- sigBody, sigSuccess := getFileUrl(sigUrl)
+ sigBody, error := getFileUrl(sigUrl)
- if !sigSuccess {
- fmt.Println("error getting signature")
- return false
+ if error != nil {
+ return nil, error
}
// Verify signature
@@ -87,46 +54,54 @@ func getDiscoJson(jsonFile string, structure interface{}) bool {
verifySuccess, verifyErr := Verify(string(sigBody), fileBody, jsonFile, previousSigTime, forcePrehash)
if !verifySuccess || verifyErr != nil {
- fmt.Printf("signature is invalid with error: %s\n", verifyErr)
- return false
+ return nil, detailedVPNError{errVerifySigError, "Signature is not valid", verifyErr}
}
- // Parse the json using the predefined struct
- error := json.Unmarshal([]byte(fileBody), &structure)
- if error != nil {
- fmt.Println("error parsing server json")
- return false
- }
+ return fileBody, nil
+}
+
+// Get the organization list
+func GetOrganizationsList() ([]byte, error) {
+ return getDiscoFile("organization_list.json")
+}
- return true
+// Get the server list
+func getServersList() ([]byte, error) {
+ return getDiscoFile("server_list.json")
}
-// Global maps that are used for storing info
-var organizationsMap = map[uint64]organizations{}
-var serversMap = map[uint64]servers{}
+// RequestErrorCode Simplified error code for public interface.
+type RequestErrorCode = VPNErrorCode
+type RequestError = VPNError
+// detailedRequestErrorCode used for unit tests.
+type detailedRequestErrorCode = detailedVPNErrorCode
+type detailedRequestError = detailedVPNError
-// Get the organization list
-// Returns the unix timestamp of the data
-func GetOrganizationsList() uint64 {
- organizations := organizations{}
- success := getDiscoJson("organization_list.json", &organizations)
+const (
+ ErrRequestFileError RequestErrorCode = iota + 1
+ ErrVerifySigError
+)
- if success {
- organizationsMap[organizations.V] = organizations
- }
+const (
+ errRequestFileError detailedRequestErrorCode = iota + 1
+ errRequestFileHTTPError
+ errRequestFileReadError
+ errVerifySigError
+)
- return organizations.V
+func (err detailedRequestError) ToRequestError() RequestError {
+ return RequestError{err.Code.ToRequestErrorCode(), err}
}
-// Get the server list
-// Return the unix timestamp of the data
-func GetServerList() uint64 {
- servers := servers{}
- success := getDiscoJson("server_list.json", &servers)
-
- if success {
- serversMap[servers.V] = servers
+func (code detailedRequestErrorCode) ToRequestErrorCode() RequestErrorCode {
+ switch code {
+ case errRequestFileError:
+ case errRequestFileReadError:
+ case errRequestFileHTTPError:
+ return ErrRequestFileError
+ return ErrRequestFileError
+ case errVerifySigError:
+ return ErrVerifySigError
}
-
- return servers.V
+ panic("invalid detailedRequestErrorCode")
}
diff --git a/src/verify.go b/src/verify.go
index b7077b8..c9aa573 100644
--- a/src/verify.go
+++ b/src/verify.go
@@ -55,28 +55,6 @@ func InsecureTestingSetExtraKey(keyString string) {
extraKey = keyString
}
-// VerifyErrorCode Simplified error code for public interface.
-type VerifyErrorCode int8
-
-const (
- ErrUnknownExpectedFileName VerifyErrorCode = iota + 1 // Unknown expected file name specified. The signature has not been verified.
- ErrInvalidSignature // Signature is invalid (for the expected file type).
- ErrInvalidSignatureUnknownKey // Signature was created with an unknown key and has not been verified.
- ErrTooOld // Signature timestamp smaller than specified minimum signing time (rollback).
-)
-
-type VerifyError struct {
- Code VerifyErrorCode
- Detailed detailedVerifyError
-}
-
-func (err VerifyError) Error() string {
- return err.Detailed.Error()
-}
-func (err VerifyError) Unwrap() error {
- return err.Detailed
-}
-
// verifyWithKeys verifies the Minisign signature in signatureFileContent (minisig file format) over the server_list/organization_list JSON in signedJson.
//
// Verification is performed using a matching key in allowedPublicKeys.
@@ -145,8 +123,20 @@ func verifyWithKeys(signatureFileContent string, signedJson []byte, expectedFile
return false, detailedVerifyError{errWrongKey, "signature was created with an unknown key", nil}
}
+// VerifyErrorCode Simplified error code for public interface.
+type VerifyErrorCode = VPNErrorCode
+type VerifyError = VPNError
// detailedVerifyErrorCode used for unit tests.
-type detailedVerifyErrorCode int8
+type detailedVerifyErrorCode = detailedVPNErrorCode
+type detailedVerifyError = detailedVPNError
+
+
+const (
+ ErrUnknownExpectedFileName VerifyErrorCode = iota + 1 // Unknown expected file name specified. The signature has not been verified.
+ ErrInvalidSignature // Signature is invalid (for the expected file type).
+ ErrInvalidSignatureUnknownKey // Signature was created with an unknown key and has not been verified.
+ ErrTooOld // Signature timestamp smaller than specified minimum signing time (rollback).
+)
const (
errUnknownExpectedFileName detailedVerifyErrorCode = iota + 1
@@ -160,6 +150,10 @@ const (
errWrongKey
)
+func (err detailedVerifyError) ToVerifyError() VerifyError {
+ return VerifyError{err.Code.ToVerifyErrorCode(), err}
+}
+
func (code detailedVerifyErrorCode) ToVerifyErrorCode() VerifyErrorCode {
switch code {
case errUnknownExpectedFileName:
@@ -184,19 +178,3 @@ func (code detailedVerifyErrorCode) ToVerifyErrorCode() VerifyErrorCode {
panic("invalid detailedVerifyErrorCode")
}
-type detailedVerifyError struct {
- Code detailedVerifyErrorCode
- Message string
- Cause error
-}
-
-func (err detailedVerifyError) Error() string {
- return err.Message
-}
-func (err detailedVerifyError) Unwrap() error {
- return err.Cause
-}
-
-func (err detailedVerifyError) ToVerifyError() VerifyError {
- return VerifyError{err.Code.ToVerifyErrorCode(), err}
-}