| // Copyright (c) HashiCorp, Inc. |
| // SPDX-License-Identifier: MPL-2.0 |
| |
| package osutil |
| |
| import ( |
| "fmt" |
| "io/fs" |
| "os" |
| ) |
| |
| func IsWriteGroup(mode os.FileMode) bool { |
| return mode&0o20 != 0 |
| } |
| |
| func IsWriteOther(mode os.FileMode) bool { |
| return mode&0o02 != 0 |
| } |
| |
| func checkPathInfo(info fs.FileInfo, path string, uid int, permissions int) error { |
| err := FileUidMatch(info, path, uid) |
| if err != nil { |
| return err |
| } |
| err = FilePermissionsMatch(info, path, permissions) |
| if err != nil { |
| return err |
| } |
| return nil |
| } |
| |
| func FilePermissionsMatch(info fs.FileInfo, path string, permissions int) error { |
| if permissions != 0 && int(info.Mode().Perm()) != permissions { |
| return fmt.Errorf("path %q does not have permissions %o", path, permissions) |
| } |
| if permissions == 0 && (IsWriteOther(info.Mode()) || IsWriteGroup(info.Mode())) { |
| return fmt.Errorf("path %q has insecure permissions %o. Vault expects no write permissions for group or others", path, info.Mode().Perm()) |
| } |
| |
| return nil |
| } |
| |
| // OwnerPermissionsMatch checks if vault user is the owner and permissions are secure for input path |
| func OwnerPermissionsMatch(path string, uid int, permissions int) error { |
| if path == "" { |
| return fmt.Errorf("could not verify permissions for path. No path provided ") |
| } |
| |
| info, err := os.Stat(path) |
| if err != nil { |
| return fmt.Errorf("error stating %q: %w", path, err) |
| } |
| if info.Mode()&os.ModeSymlink != 0 { |
| symLinkInfo, err := os.Lstat(path) |
| if err != nil { |
| return fmt.Errorf("error stating %q: %w", path, err) |
| } |
| err = checkPathInfo(symLinkInfo, path, uid, permissions) |
| if err != nil { |
| return err |
| } |
| } |
| err = checkPathInfo(info, path, uid, permissions) |
| if err != nil { |
| return err |
| } |
| |
| return nil |
| } |
| |
| // OwnerPermissionsMatchFile checks if vault user is the owner and permissions are secure for the input file |
| func OwnerPermissionsMatchFile(file *os.File, uid int, permissions int) error { |
| info, err := file.Stat() |
| if err != nil { |
| return fmt.Errorf("file stat error on path %q: %w", file.Name(), err) |
| } |
| err = checkPathInfo(info, file.Name(), uid, permissions) |
| if err != nil { |
| return err |
| } |
| |
| return nil |
| } |