From f1122a019c4f2c6f0e21fca78835f2a967488df5 Mon Sep 17 00:00:00 2001 From: Samuel Lorch Date: Fri, 21 Jan 2022 13:46:26 +0100 Subject: [PATCH] add uuid check before insering into url --- api/comments.go | 19 ++++++++++++++++++- api/favorites.go | 11 ++++++++++- api/folders.go | 21 +++++++++++++++++++-- api/gpgkey.go | 5 +++++ api/groups.go | 19 ++++++++++++++++++- api/misc.go | 10 ++++++++++ api/permissions.go | 5 +++++ api/resource_types.go | 5 +++++ api/resources.go | 21 +++++++++++++++++++-- api/secrets.go | 5 +++++ api/setup.go | 15 ++++++++++++++- api/share.go | 17 +++++++++++++++-- api/users.go | 21 +++++++++++++++++++-- 13 files changed, 162 insertions(+), 12 deletions(-) diff --git a/api/comments.go b/api/comments.go index 05f4c02..b4c5521 100644 --- a/api/comments.go +++ b/api/comments.go @@ -3,6 +3,7 @@ package api import ( "context" "encoding/json" + "fmt" ) // Comment is a Comment @@ -29,6 +30,10 @@ type GetCommentsOptions struct { // GetComments gets all Passbolt Comments an The Specified Resource func (c *Client) GetComments(ctx context.Context, resourceID string, opts *GetCommentsOptions) ([]Comment, error) { + err := checkUUIDFormat(resourceID) + if err != nil { + return nil, fmt.Errorf("Checking ID format: %w", err) + } msg, err := c.DoCustomRequest(ctx, "GET", "/comments/resource/"+resourceID+".json", "v2", nil, opts) if err != nil { return nil, err @@ -44,6 +49,10 @@ func (c *Client) GetComments(ctx context.Context, resourceID string, opts *GetCo // CreateComment Creates a new Passbolt Comment func (c *Client) CreateComment(ctx context.Context, resourceID string, comment Comment) (*Comment, error) { + err := checkUUIDFormat(resourceID) + if err != nil { + return nil, fmt.Errorf("Checking ID format: %w", err) + } msg, err := c.DoCustomRequest(ctx, "POST", "/comments/resource/"+resourceID+".json", "v2", comment, nil) if err != nil { return nil, err @@ -58,6 +67,10 @@ func (c *Client) CreateComment(ctx context.Context, resourceID string, comment C // UpdateComment Updates a existing Passbolt Comment func (c *Client) UpdateComment(ctx context.Context, commentID string, comment Comment) (*Comment, error) { + err := checkUUIDFormat(commentID) + if err != nil { + return nil, fmt.Errorf("Checking ID format: %w", err) + } msg, err := c.DoCustomRequest(ctx, "PUT", "/comments/"+commentID+".json", "v2", comment, nil) if err != nil { return nil, err @@ -72,7 +85,11 @@ func (c *Client) UpdateComment(ctx context.Context, commentID string, comment Co // DeleteComment Deletes a Passbolt Comment func (c *Client) DeleteComment(ctx context.Context, commentID string) error { - _, err := c.DoCustomRequest(ctx, "DELETE", "/comments/"+commentID+".json", "v2", nil, nil) + err := checkUUIDFormat(commentID) + if err != nil { + return fmt.Errorf("Checking ID format: %w", err) + } + _, err = c.DoCustomRequest(ctx, "DELETE", "/comments/"+commentID+".json", "v2", nil, nil) if err != nil { return err } diff --git a/api/favorites.go b/api/favorites.go index 11248cf..b9dac57 100644 --- a/api/favorites.go +++ b/api/favorites.go @@ -3,6 +3,7 @@ package api import ( "context" "encoding/json" + "fmt" ) // Favorite is a Favorite @@ -16,6 +17,10 @@ type Favorite struct { // CreateFavorite Creates a new Passbolt Favorite for the given Resource ID func (c *Client) CreateFavorite(ctx context.Context, resourceID string) (*Favorite, error) { + err := checkUUIDFormat(resourceID) + if err != nil { + return nil, fmt.Errorf("Checking ID format: %w", err) + } msg, err := c.DoCustomRequest(ctx, "POST", "/favorites/resource/"+resourceID+".json", "v2", nil, nil) if err != nil { return nil, err @@ -31,7 +36,11 @@ func (c *Client) CreateFavorite(ctx context.Context, resourceID string) (*Favori // DeleteFavorite Deletes a Passbolt Favorite func (c *Client) DeleteFavorite(ctx context.Context, favoriteID string) error { - _, err := c.DoCustomRequest(ctx, "DELETE", "/favorites/"+favoriteID+".json", "v2", nil, nil) + err := checkUUIDFormat(favoriteID) + if err != nil { + return fmt.Errorf("Checking ID format: %w", err) + } + _, err = c.DoCustomRequest(ctx, "DELETE", "/favorites/"+favoriteID+".json", "v2", nil, nil) if err != nil { return err } diff --git a/api/folders.go b/api/folders.go index 49926eb..22984a3 100644 --- a/api/folders.go +++ b/api/folders.go @@ -3,6 +3,7 @@ package api import ( "context" "encoding/json" + "fmt" ) // Folder is a Folder @@ -83,6 +84,10 @@ func (c *Client) CreateFolder(ctx context.Context, folder Folder) (*Folder, erro // GetFolder gets a Passbolt Folder func (c *Client) GetFolder(ctx context.Context, folderID string, opts *GetFolderOptions) (*Folder, error) { + err := checkUUIDFormat(folderID) + if err != nil { + return nil, fmt.Errorf("Checking ID format: %w", err) + } msg, err := c.DoCustomRequest(ctx, "GET", "/folders/"+folderID+".json", "v2", nil, opts) if err != nil { return nil, err @@ -98,6 +103,10 @@ func (c *Client) GetFolder(ctx context.Context, folderID string, opts *GetFolder // UpdateFolder Updates a existing Passbolt Folder func (c *Client) UpdateFolder(ctx context.Context, folderID string, folder Folder) (*Folder, error) { + err := checkUUIDFormat(folderID) + if err != nil { + return nil, fmt.Errorf("Checking ID format: %w", err) + } msg, err := c.DoCustomRequest(ctx, "PUT", "/folders/"+folderID+".json", "v2", folder, nil) if err != nil { return nil, err @@ -112,7 +121,11 @@ func (c *Client) UpdateFolder(ctx context.Context, folderID string, folder Folde // DeleteFolder Deletes a Passbolt Folder func (c *Client) DeleteFolder(ctx context.Context, folderID string) error { - _, err := c.DoCustomRequest(ctx, "DELETE", "/folders/"+folderID+".json", "v2", nil, nil) + err := checkUUIDFormat(folderID) + if err != nil { + return fmt.Errorf("Checking ID format: %w", err) + } + _, err = c.DoCustomRequest(ctx, "DELETE", "/folders/"+folderID+".json", "v2", nil, nil) if err != nil { return err } @@ -121,7 +134,11 @@ func (c *Client) DeleteFolder(ctx context.Context, folderID string) error { // MoveFolder Moves a Passbolt Folder func (c *Client) MoveFolder(ctx context.Context, folderID, folderParentID string) error { - _, err := c.DoCustomRequest(ctx, "PUT", "/move/folder/"+folderID+".json", "v2", Folder{ + err := checkUUIDFormat(folderID) + if err != nil { + return fmt.Errorf("Checking ID format: %w", err) + } + _, err = c.DoCustomRequest(ctx, "PUT", "/move/folder/"+folderID+".json", "v2", Folder{ FolderParentID: folderParentID, }, nil) if err != nil { diff --git a/api/gpgkey.go b/api/gpgkey.go index f4ce59e..b78109e 100644 --- a/api/gpgkey.go +++ b/api/gpgkey.go @@ -3,6 +3,7 @@ package api import ( "context" "encoding/json" + "fmt" ) // GPGKey is a GPGKey @@ -43,6 +44,10 @@ func (c *Client) GetGPGKeys(ctx context.Context, opts *GetGPGKeysOptions) ([]GPG // GetGPGKey gets a Passbolt GPGKey func (c *Client) GetGPGKey(ctx context.Context, gpgkeyID string) (*GPGKey, error) { + err := checkUUIDFormat(gpgkeyID) + if err != nil { + return nil, fmt.Errorf("Checking ID format: %w", err) + } msg, err := c.DoCustomRequest(ctx, "GET", "/gpgkeys/"+gpgkeyID+".json", "v2", nil, nil) if err != nil { return nil, err diff --git a/api/groups.go b/api/groups.go index 74c25a3..d04a518 100644 --- a/api/groups.go +++ b/api/groups.go @@ -3,6 +3,7 @@ package api import ( "context" "encoding/json" + "fmt" ) //Group is a Group @@ -124,6 +125,10 @@ func (c *Client) CreateGroup(ctx context.Context, group Group) (*Group, error) { // GetGroup gets a Passbolt Group func (c *Client) GetGroup(ctx context.Context, groupID string) (*Group, error) { + err := checkUUIDFormat(groupID) + if err != nil { + return nil, fmt.Errorf("Checking ID format: %w", err) + } msg, err := c.DoCustomRequest(ctx, "GET", "/groups/"+groupID+".json", "v2", nil, nil) if err != nil { return nil, err @@ -139,6 +144,10 @@ func (c *Client) GetGroup(ctx context.Context, groupID string) (*Group, error) { // UpdateGroup Updates a existing Passbolt Group func (c *Client) UpdateGroup(ctx context.Context, groupID string, update GroupUpdate) (*Group, error) { + err := checkUUIDFormat(groupID) + if err != nil { + return nil, fmt.Errorf("Checking ID format: %w", err) + } msg, err := c.DoCustomRequest(ctx, "PUT", "/groups/"+groupID+".json", "v2", update, nil) if err != nil { return nil, err @@ -153,6 +162,10 @@ func (c *Client) UpdateGroup(ctx context.Context, groupID string, update GroupUp // UpdateGroupDryRun Checks that a Passbolt Group update passes validation func (c *Client) UpdateGroupDryRun(ctx context.Context, groupID string, update GroupUpdate) (*UpdateGroupDryRunResult, error) { + err := checkUUIDFormat(groupID) + if err != nil { + return nil, fmt.Errorf("Checking ID format: %w", err) + } msg, err := c.DoCustomRequest(ctx, "PUT", "/groups/"+groupID+"/dry-run.json", "v2", update, nil) if err != nil { return nil, err @@ -167,7 +180,11 @@ func (c *Client) UpdateGroupDryRun(ctx context.Context, groupID string, update G // DeleteGroup Deletes a Passbolt Group func (c *Client) DeleteGroup(ctx context.Context, groupID string) error { - _, err := c.DoCustomRequest(ctx, "DELETE", "/groups/"+groupID+".json", "v2", nil, nil) + err := checkUUIDFormat(groupID) + if err != nil { + return fmt.Errorf("Checking ID format: %w", err) + } + _, err = c.DoCustomRequest(ctx, "DELETE", "/groups/"+groupID+".json", "v2", nil, nil) if err != nil { return err } diff --git a/api/misc.go b/api/misc.go index 99ee9fb..ce3ff71 100644 --- a/api/misc.go +++ b/api/misc.go @@ -3,12 +3,15 @@ package api import ( "fmt" "math/rand" + "regexp" "strconv" "strings" ) const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" +var isUUID = regexp.MustCompile("^[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}$") + func randStringBytesRmndr(length int) string { b := make([]byte, length) for i := range b { @@ -41,3 +44,10 @@ func checkAuthTokenFormat(authToken string) error { } return nil } + +func checkUUIDFormat(data string) error { + if !isUUID.MatchString(data) { + return fmt.Errorf("UUID is not in the valid format xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx") + } + return nil +} diff --git a/api/permissions.go b/api/permissions.go index e60edf5..3bca4f9 100644 --- a/api/permissions.go +++ b/api/permissions.go @@ -3,6 +3,7 @@ package api import ( "context" "encoding/json" + "fmt" ) // Permission is a Permission @@ -21,6 +22,10 @@ type Permission struct { // GetResourcePermissions gets a Resources Permissions func (c *Client) GetResourcePermissions(ctx context.Context, resourceID string) ([]Permission, error) { + err := checkUUIDFormat(resourceID) + if err != nil { + return nil, fmt.Errorf("Checking ID format: %w", err) + } msg, err := c.DoCustomRequest(ctx, "GET", "/permissions/resource/"+resourceID+".json", "v2", nil, nil) if err != nil { return nil, err diff --git a/api/resource_types.go b/api/resource_types.go index 862180b..5b3a753 100644 --- a/api/resource_types.go +++ b/api/resource_types.go @@ -3,6 +3,7 @@ package api import ( "context" "encoding/json" + "fmt" ) //ResourceType is the Type of a Resource @@ -36,6 +37,10 @@ func (c *Client) GetResourceTypes(ctx context.Context, opts *GetResourceTypesOpt // GetResourceType gets a Passbolt Type func (c *Client) GetResourceType(ctx context.Context, typeID string) (*ResourceType, error) { + err := checkUUIDFormat(typeID) + if err != nil { + return nil, fmt.Errorf("Checking ID format: %w", err) + } msg, err := c.DoCustomRequest(ctx, "GET", "/resource-types/"+typeID+".json", "v2", nil, nil) if err != nil { return nil, err diff --git a/api/resources.go b/api/resources.go index 91ff97f..7fbabe6 100644 --- a/api/resources.go +++ b/api/resources.go @@ -3,6 +3,7 @@ package api import ( "context" "encoding/json" + "fmt" ) // Resource is a Resource. @@ -89,6 +90,10 @@ func (c *Client) CreateResource(ctx context.Context, resource Resource) (*Resour // GetResource gets a Passbolt Resource func (c *Client) GetResource(ctx context.Context, resourceID string) (*Resource, error) { + err := checkUUIDFormat(resourceID) + if err != nil { + return nil, fmt.Errorf("Checking ID format: %w", err) + } msg, err := c.DoCustomRequest(ctx, "GET", "/resources/"+resourceID+".json", "v2", nil, nil) if err != nil { return nil, err @@ -104,6 +109,10 @@ func (c *Client) GetResource(ctx context.Context, resourceID string) (*Resource, // UpdateResource Updates a existing Passbolt Resource func (c *Client) UpdateResource(ctx context.Context, resourceID string, resource Resource) (*Resource, error) { + err := checkUUIDFormat(resourceID) + if err != nil { + return nil, fmt.Errorf("Checking ID format: %w", err) + } msg, err := c.DoCustomRequest(ctx, "PUT", "/resources/"+resourceID+".json", "v2", resource, nil) if err != nil { return nil, err @@ -118,7 +127,11 @@ func (c *Client) UpdateResource(ctx context.Context, resourceID string, resource // DeleteResource Deletes a Passbolt Resource func (c *Client) DeleteResource(ctx context.Context, resourceID string) error { - _, err := c.DoCustomRequest(ctx, "DELETE", "/resources/"+resourceID+".json", "v2", nil, nil) + err := checkUUIDFormat(resourceID) + if err != nil { + return fmt.Errorf("Checking ID format: %w", err) + } + _, err = c.DoCustomRequest(ctx, "DELETE", "/resources/"+resourceID+".json", "v2", nil, nil) if err != nil { return err } @@ -127,7 +140,11 @@ func (c *Client) DeleteResource(ctx context.Context, resourceID string) error { // MoveResource Moves a Passbolt Resource func (c *Client) MoveResource(ctx context.Context, resourceID, folderParentID string) error { - _, err := c.DoCustomRequest(ctx, "PUT", "/move/resource/"+resourceID+".json", "v2", Resource{ + err := checkUUIDFormat(resourceID) + if err != nil { + return fmt.Errorf("Checking ID format: %w", err) + } + _, err = c.DoCustomRequest(ctx, "PUT", "/move/resource/"+resourceID+".json", "v2", Resource{ FolderParentID: folderParentID, }, nil) if err != nil { diff --git a/api/secrets.go b/api/secrets.go index 70979cd..1f63b23 100644 --- a/api/secrets.go +++ b/api/secrets.go @@ -3,6 +3,7 @@ package api import ( "context" "encoding/json" + "fmt" ) // Secret is a Secret @@ -23,6 +24,10 @@ type SecretDataTypePasswordAndDescription struct { // GetSecret gets a Passbolt Secret func (c *Client) GetSecret(ctx context.Context, resourceID string) (*Secret, error) { + err := checkUUIDFormat(resourceID) + if err != nil { + return nil, fmt.Errorf("Checking ID format: %w", err) + } msg, err := c.DoCustomRequest(ctx, "GET", "/secrets/resource/"+resourceID+".json", "v2", nil, nil) if err != nil { return nil, err diff --git a/api/setup.go b/api/setup.go index b7a941b..a0b23a7 100644 --- a/api/setup.go +++ b/api/setup.go @@ -3,6 +3,7 @@ package api import ( "context" "encoding/json" + "fmt" ) type SetupInstallResponse struct { @@ -21,6 +22,14 @@ type SetupCompleteRequest struct { // SetupInstall validates the userid and token used for Account setup, gives back the User Information func (c *Client) SetupInstall(ctx context.Context, userID, token string) (*SetupInstallResponse, error) { + err := checkUUIDFormat(userID) + if err != nil { + return nil, fmt.Errorf("Checking ID format: %w", err) + } + err = checkUUIDFormat(token) + if err != nil { + return nil, fmt.Errorf("Checking Token format: %w", err) + } msg, err := c.DoCustomRequest(ctx, "GET", "/setup/install/"+userID+"/"+token+".json", "v2", nil, nil) if err != nil { return nil, err @@ -36,7 +45,11 @@ func (c *Client) SetupInstall(ctx context.Context, userID, token string) (*Setup // SetupComplete Completes setup of a Passbolt Account func (c *Client) SetupComplete(ctx context.Context, userID string, request SetupCompleteRequest) error { - _, err := c.DoCustomRequest(ctx, "POST", "/setup/complete/"+userID+".json", "v2", request, nil) + err := checkUUIDFormat(userID) + if err != nil { + return fmt.Errorf("Checking ID format: %w", err) + } + _, err = c.DoCustomRequest(ctx, "POST", "/setup/complete/"+userID+".json", "v2", request, nil) if err != nil { return err } diff --git a/api/share.go b/api/share.go index 8e940f0..225a805 100644 --- a/api/share.go +++ b/api/share.go @@ -3,6 +3,7 @@ package api import ( "context" "encoding/json" + "fmt" ) // ResourceShareRequest is a ResourceShareRequest @@ -61,7 +62,11 @@ func (c *Client) SearchAROs(ctx context.Context, opts SearchAROsOptions) ([]ARO, // ShareResource Shares a Resource with AROs func (c *Client) ShareResource(ctx context.Context, resourceID string, shareRequest ResourceShareRequest) error { - _, err := c.DoCustomRequest(ctx, "PUT", "/share/resource/"+resourceID+".json", "v2", shareRequest, nil) + err := checkUUIDFormat(resourceID) + if err != nil { + return fmt.Errorf("Checking ID format: %w", err) + } + _, err = c.DoCustomRequest(ctx, "PUT", "/share/resource/"+resourceID+".json", "v2", shareRequest, nil) if err != nil { return err } @@ -71,8 +76,12 @@ func (c *Client) ShareResource(ctx context.Context, resourceID string, shareRequ // ShareFolder Shares a Folder with AROs func (c *Client) ShareFolder(ctx context.Context, folderID string, permissions []Permission) error { + err := checkUUIDFormat(folderID) + if err != nil { + return fmt.Errorf("Checking ID format: %w", err) + } f := Folder{Permissions: permissions} - _, err := c.DoCustomRequest(ctx, "PUT", "/share/folder/"+folderID+".json", "v2", f, nil) + _, err = c.DoCustomRequest(ctx, "PUT", "/share/folder/"+folderID+".json", "v2", f, nil) if err != nil { return err } @@ -82,6 +91,10 @@ func (c *Client) ShareFolder(ctx context.Context, folderID string, permissions [ // SimulateShareResource Simulates Shareing a Resource with AROs func (c *Client) SimulateShareResource(ctx context.Context, resourceID string, shareRequest ResourceShareRequest) (*ResourceShareSimulationResult, error) { + err := checkUUIDFormat(resourceID) + if err != nil { + return nil, fmt.Errorf("Checking ID format: %w", err) + } msg, err := c.DoCustomRequest(ctx, "POST", "/share/simulate/resource/"+resourceID+".json", "v2", shareRequest, nil) if err != nil { return nil, err diff --git a/api/users.go b/api/users.go index 9cea6c8..9ce240b 100644 --- a/api/users.go +++ b/api/users.go @@ -3,6 +3,7 @@ package api import ( "context" "encoding/json" + "fmt" ) const UserLocaleENUK = "en-UK" @@ -81,6 +82,10 @@ func (c *Client) GetMe(ctx context.Context) (*User, error) { // GetUser gets a Passbolt User func (c *Client) GetUser(ctx context.Context, userID string) (*User, error) { + err := checkUUIDFormat(userID) + if err != nil { + return nil, fmt.Errorf("Checking ID format: %w", err) + } msg, err := c.DoCustomRequest(ctx, "GET", "/users/"+userID+".json", "v2", nil, nil) if err != nil { return nil, err @@ -96,6 +101,10 @@ func (c *Client) GetUser(ctx context.Context, userID string) (*User, error) { // UpdateUser Updates a existing Passbolt User func (c *Client) UpdateUser(ctx context.Context, userID string, user User) (*User, error) { + err := checkUUIDFormat(userID) + if err != nil { + return nil, fmt.Errorf("Checking ID format: %w", err) + } msg, err := c.DoCustomRequest(ctx, "PUT", "/users/"+userID+".json", "v2", user, nil) if err != nil { return nil, err @@ -110,7 +119,11 @@ func (c *Client) UpdateUser(ctx context.Context, userID string, user User) (*Use // DeleteUser Deletes a Passbolt User func (c *Client) DeleteUser(ctx context.Context, userID string) error { - _, err := c.DoCustomRequest(ctx, "DELETE", "/users/"+userID+".json", "v2", nil, nil) + err := checkUUIDFormat(userID) + if err != nil { + return fmt.Errorf("Checking ID format: %w", err) + } + _, err = c.DoCustomRequest(ctx, "DELETE", "/users/"+userID+".json", "v2", nil, nil) if err != nil { return err } @@ -119,7 +132,11 @@ func (c *Client) DeleteUser(ctx context.Context, userID string) error { // DeleteUserDryrun Check if a Passbolt User is Deleteable func (c *Client) DeleteUserDryrun(ctx context.Context, userID string) error { - _, err := c.DoCustomRequest(ctx, "DELETE", "/users/"+userID+"/dry-run.json", "v2", nil, nil) + err := checkUUIDFormat(userID) + if err != nil { + return fmt.Errorf("Checking ID format: %w", err) + } + _, err = c.DoCustomRequest(ctx, "DELETE", "/users/"+userID+"/dry-run.json", "v2", nil, nil) if err != nil { return err }