fix(auth): isolate bounded OIDC cleanup
This commit is contained in:
@@ -22,7 +22,8 @@ const (
|
||||
maximumProtocolBytes = 64 * 1024
|
||||
maximumSessionBytes = 16 * 1024
|
||||
maximumOIDCStateBytes = 8 * 1024
|
||||
maximumEntries = 256
|
||||
defaultMaximumEntries = 256
|
||||
maximumEntries = 512
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -33,12 +34,13 @@ var (
|
||||
)
|
||||
|
||||
type request struct {
|
||||
Version int `json:"version"`
|
||||
Operation string `json:"operation"`
|
||||
Root string `json:"root"`
|
||||
Directory string `json:"directory"`
|
||||
Filename string `json:"filename,omitempty"`
|
||||
ContentBase64 string `json:"contentBase64,omitempty"`
|
||||
Version int `json:"version"`
|
||||
Operation string `json:"operation"`
|
||||
Root string `json:"root"`
|
||||
Directory string `json:"directory"`
|
||||
Filename string `json:"filename,omitempty"`
|
||||
ContentBase64 string `json:"contentBase64,omitempty"`
|
||||
MaximumEntries int `json:"maximumEntries,omitempty"`
|
||||
}
|
||||
|
||||
type response struct {
|
||||
@@ -137,7 +139,11 @@ func execute(input request) (response, error) {
|
||||
}
|
||||
return response{Version: protocolVersion, OK: true, Removed: removed}, nil
|
||||
case "list":
|
||||
entries, err := safeio.ListCanonicalPrivateDirectory(directory, maximumEntries)
|
||||
limit := input.MaximumEntries
|
||||
if limit == 0 {
|
||||
limit = defaultMaximumEntries
|
||||
}
|
||||
entries, err := safeio.ListCanonicalPrivateDirectory(directory, limit)
|
||||
if err != nil {
|
||||
return response{}, errInvalid
|
||||
}
|
||||
@@ -175,17 +181,18 @@ func execute(input request) (response, error) {
|
||||
|
||||
func validOperationShape(input request) bool {
|
||||
noContents := input.ContentBase64 == ""
|
||||
noMaximumEntries := input.MaximumEntries == 0
|
||||
switch input.Operation {
|
||||
case "create", "replace":
|
||||
return digestFilename.MatchString(input.Filename) || (input.Operation == "create" && input.Directory == "oidc" && oidcSlotFilename.MatchString(input.Filename))
|
||||
return noMaximumEntries && (digestFilename.MatchString(input.Filename) || (input.Operation == "create" && input.Directory == "oidc" && oidcSlotFilename.MatchString(input.Filename)))
|
||||
case "read":
|
||||
return noContents && (digestFilename.MatchString(input.Filename) || (input.Directory == "oidc" && oidcSlotFilename.MatchString(input.Filename)))
|
||||
return noContents && noMaximumEntries && (digestFilename.MatchString(input.Filename) || (input.Directory == "oidc" && oidcSlotFilename.MatchString(input.Filename)))
|
||||
case "remove":
|
||||
return noContents && (digestFilename.MatchString(input.Filename) || (input.Directory == "oidc" && (claimFilename.MatchString(input.Filename) || oidcSlotFilename.MatchString(input.Filename))))
|
||||
return noContents && noMaximumEntries && (digestFilename.MatchString(input.Filename) || (input.Directory == "oidc" && (claimFilename.MatchString(input.Filename) || oidcSlotFilename.MatchString(input.Filename))))
|
||||
case "list":
|
||||
return input.Filename == "" && noContents
|
||||
return input.Filename == "" && noContents && input.MaximumEntries >= 0 && input.MaximumEntries <= maximumEntries
|
||||
case "claim-consume", "read-claim", "remove-claim":
|
||||
return input.Directory == "oidc" && noContents && digestFilename.MatchString(input.Filename)
|
||||
return input.Directory == "oidc" && noContents && noMaximumEntries && digestFilename.MatchString(input.Filename)
|
||||
default:
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
@@ -15,6 +16,24 @@ import (
|
||||
"github.com/aritmolab/thothii/tools/tht/internal/testsupport"
|
||||
)
|
||||
|
||||
func TestProtocolListUsesACallerSuppliedBound(t *testing.T) {
|
||||
root := filepath.Join(privateTestRoot(t), "auth")
|
||||
for index := 0; index < 300; index++ {
|
||||
filename := fmt.Sprintf("%064x.json", index)
|
||||
runRequest(t, request{Version: 1, Operation: "create", Root: root, Directory: "sessions", Filename: filename, ContentBase64: base64.StdEncoding.EncodeToString([]byte("record"))})
|
||||
}
|
||||
|
||||
listed := runRequest(t, request{Version: 1, Operation: "list", Root: root, Directory: "sessions", MaximumEntries: 300})
|
||||
if listed.Entries == nil || len(*listed.Entries) != 300 {
|
||||
t.Fatalf("bounded list size = %d, want 300", len(*listed.Entries))
|
||||
}
|
||||
filename := fmt.Sprintf("%064x.json", 300)
|
||||
runRequest(t, request{Version: 1, Operation: "create", Root: root, Directory: "sessions", Filename: filename, ContentBase64: base64.StdEncoding.EncodeToString([]byte("record"))})
|
||||
runRejected(t, request{Version: 1, Operation: "list", Root: root, Directory: "sessions", MaximumEntries: 300})
|
||||
runRejected(t, request{Version: 1, Operation: "list", Root: root, Directory: "sessions", MaximumEntries: maximumEntries + 1})
|
||||
runRejected(t, request{Version: 1, Operation: "read", Root: root, Directory: "sessions", Filename: filename, MaximumEntries: 1})
|
||||
}
|
||||
|
||||
func TestProtocolCreatesReadsReplacesListsAndRemovesPrivateRecord(t *testing.T) {
|
||||
root := filepath.Join(privateTestRoot(t), "auth")
|
||||
filename := "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.json"
|
||||
|
||||
Reference in New Issue
Block a user