feat(auth): add safe Argon2id local user registry
This commit is contained in:
@@ -2,6 +2,8 @@
|
||||
package safeio
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"io"
|
||||
"os"
|
||||
@@ -36,8 +38,8 @@ func readBoundedRegularFile(path string, file *os.File, maximum int64) ([]byte,
|
||||
if err != nil || !after.Mode().IsRegular() || !hasSingleLink(after) || !os.SameFile(info, after) {
|
||||
return nil, ErrUnsafeFile
|
||||
}
|
||||
current, err := os.Stat(path)
|
||||
if err != nil || !os.SameFile(info, current) {
|
||||
current, err := os.Lstat(path)
|
||||
if err != nil || !current.Mode().IsRegular() || current.Mode()&os.ModeSymlink != 0 || !hasSingleLink(current) || !os.SameFile(info, current) {
|
||||
return nil, ErrUnsafeFile
|
||||
}
|
||||
return contents, nil
|
||||
@@ -86,6 +88,24 @@ func WriteCanonicalNewFile(path string, contents []byte, mode os.FileMode) error
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReplaceCanonicalRegular durably replaces one existing private regular file without following
|
||||
// symlinked path components. Platform implementations keep the temporary file in the target
|
||||
// directory and use the platform's atomic replace primitive.
|
||||
func ReplaceCanonicalRegular(path string, contents []byte, mode os.FileMode) error {
|
||||
if err := ValidateCanonicalPath(path); err != nil || mode.Perm() != 0o600 || mode&os.ModeType != 0 {
|
||||
return ErrUnsafeFile
|
||||
}
|
||||
return replaceCanonicalRegular(path, contents)
|
||||
}
|
||||
|
||||
func randomTemporaryName() (string, error) {
|
||||
bytes := make([]byte, 16)
|
||||
if _, err := rand.Read(bytes); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return ".tht-auth-" + hex.EncodeToString(bytes) + ".tmp", nil
|
||||
}
|
||||
|
||||
func requireCanonicalDirectory(path string) error {
|
||||
if err := ValidateCanonicalPath(path); err != nil {
|
||||
return err
|
||||
|
||||
Reference in New Issue
Block a user