diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/error.go | 30 | ||||
| -rw-r--r-- | src/server.go | 127 | ||||
| -rw-r--r-- | src/verify.go | 56 |
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} -} |
