fix(auth): add Windows session storage bridge
This commit is contained in:
@@ -71,6 +71,50 @@ func ReadCanonicalUTF8(path string, maximum int64) (string, error) {
|
||||
return string(contents), nil
|
||||
}
|
||||
|
||||
// ReadCanonicalPrivateRegular reads one owner-only private record and revalidates its metadata
|
||||
// after the bounded read. It intentionally rejects ordinary hard links; OIDC's explicitly named
|
||||
// atomic claim pair uses ReadCanonicalPrivateClaim instead.
|
||||
func ReadCanonicalPrivateRegular(path string, maximum int64) ([]byte, error) {
|
||||
return readCanonicalPrivateRegular(path, maximum)
|
||||
}
|
||||
|
||||
// PrivateDirectoryEntry is a bounded, untrusted directory listing item. Callers must still
|
||||
// validate each filename and record before using it.
|
||||
type PrivateDirectoryEntry struct {
|
||||
Name string
|
||||
ModifiedUnixMs int64
|
||||
}
|
||||
|
||||
// ListCanonicalPrivateDirectory lists regular, non-symlinked direct children from an owner-only
|
||||
// directory. It returns no content and bounds the number of entries before allocating output.
|
||||
func ListCanonicalPrivateDirectory(path string, maximumEntries int) ([]PrivateDirectoryEntry, error) {
|
||||
if maximumEntries < 1 || maximumEntries > 4096 {
|
||||
return nil, ErrUnsafeFile
|
||||
}
|
||||
if err := ValidatePrivateDirectory(path); err != nil {
|
||||
return nil, ErrUnsafeFile
|
||||
}
|
||||
entries, err := os.ReadDir(path)
|
||||
if err != nil || len(entries) > maximumEntries {
|
||||
return nil, ErrUnsafeFile
|
||||
}
|
||||
result := make([]PrivateDirectoryEntry, 0, len(entries))
|
||||
for _, entry := range entries {
|
||||
if entry.Name() == "" || strings.Contains(entry.Name(), string(filepath.Separator)) {
|
||||
return nil, ErrUnsafeFile
|
||||
}
|
||||
info, err := os.Lstat(filepath.Join(path, entry.Name()))
|
||||
if err != nil || !info.Mode().IsRegular() || info.Mode()&os.ModeSymlink != 0 {
|
||||
return nil, ErrUnsafeFile
|
||||
}
|
||||
result = append(result, PrivateDirectoryEntry{Name: entry.Name(), ModifiedUnixMs: info.ModTime().UnixMilli()})
|
||||
}
|
||||
if err := ValidatePrivateDirectory(path); err != nil {
|
||||
return nil, ErrUnsafeFile
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func WriteCanonicalNewFile(path string, contents []byte, mode os.FileMode) error {
|
||||
if err := ValidateCanonicalPath(path); err != nil {
|
||||
return err
|
||||
@@ -127,6 +171,42 @@ func RemoveCanonicalPrivateRegular(path string) error {
|
||||
return removeCanonicalPrivateRegular(path)
|
||||
}
|
||||
|
||||
// ClaimCanonicalPrivateRegular atomically creates a second, explicit private hard link to one
|
||||
// existing record. It is used only for digest-named, single-use OIDC state claims.
|
||||
func ClaimCanonicalPrivateRegular(source, claim string) (bool, error) {
|
||||
if err := validateClaimPaths(source, claim); err != nil {
|
||||
return false, ErrUnsafeFile
|
||||
}
|
||||
return claimCanonicalPrivateRegular(source, claim)
|
||||
}
|
||||
|
||||
// ReadCanonicalPrivateClaim reads a verified two-link source/claim pair. found=false means the
|
||||
// state has already been consumed or a winning process is between its two removal steps.
|
||||
func ReadCanonicalPrivateClaim(source, claim string, maximum int64) ([]byte, bool, error) {
|
||||
if maximum < 0 || maximum == int64(^uint64(0)>>1) || validateClaimPaths(source, claim) != nil {
|
||||
return nil, false, ErrUnsafeFile
|
||||
}
|
||||
return readCanonicalPrivateClaim(source, claim, maximum)
|
||||
}
|
||||
|
||||
// RemoveCanonicalPrivateClaim removes exactly a verified two-link source/claim pair.
|
||||
func RemoveCanonicalPrivateClaim(source, claim string) (bool, error) {
|
||||
if err := validateClaimPaths(source, claim); err != nil {
|
||||
return false, ErrUnsafeFile
|
||||
}
|
||||
return removeCanonicalPrivateClaim(source, claim)
|
||||
}
|
||||
|
||||
func validateClaimPaths(source, claim string) error {
|
||||
if ValidateCanonicalPath(source) != nil || ValidateCanonicalPath(claim) != nil || filepath.Dir(source) != filepath.Dir(claim) {
|
||||
return ErrUnsafeFile
|
||||
}
|
||||
if err := ValidatePrivateDirectory(filepath.Dir(source)); err != nil {
|
||||
return ErrUnsafeFile
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func randomTemporaryName() (string, error) {
|
||||
bytes := make([]byte, 16)
|
||||
if _, err := rand.Read(bytes); err != nil {
|
||||
|
||||
Reference in New Issue
Block a user