aboutsummaryrefslogtreecommitdiff
path: root/vendor/github.com/lib/pq/ssl_permissions.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/lib/pq/ssl_permissions.go')
-rw-r--r--vendor/github.com/lib/pq/ssl_permissions.go80
1 files changed, 76 insertions, 4 deletions
diff --git a/vendor/github.com/lib/pq/ssl_permissions.go b/vendor/github.com/lib/pq/ssl_permissions.go
index 014af6a..d587f10 100644
--- a/vendor/github.com/lib/pq/ssl_permissions.go
+++ b/vendor/github.com/lib/pq/ssl_permissions.go
@@ -3,7 +3,28 @@
package pq
-import "os"
+import (
+ "errors"
+ "os"
+ "syscall"
+)
+
+const (
+ rootUserID = uint32(0)
+
+ // The maximum permissions that a private key file owned by a regular user
+ // is allowed to have. This translates to u=rw.
+ maxUserOwnedKeyPermissions os.FileMode = 0600
+
+ // The maximum permissions that a private key file owned by root is allowed
+ // to have. This translates to u=rw,g=r.
+ maxRootOwnedKeyPermissions os.FileMode = 0640
+)
+
+var (
+ errSSLKeyHasUnacceptableUserPermissions = errors.New("permissions for files not owned by root should be u=rw (0600) or less")
+ errSSLKeyHasUnacceptableRootPermissions = errors.New("permissions for root owned files should be u=rw,g=r (0640) or less")
+)
// sslKeyPermissions checks the permissions on user-supplied ssl key files.
// The key file should have very little access.
@@ -14,8 +35,59 @@ func sslKeyPermissions(sslkey string) error {
if err != nil {
return err
}
- if info.Mode().Perm()&0077 != 0 {
- return ErrSSLKeyHasWorldPermissions
+
+ err = hasCorrectPermissions(info)
+
+ // return ErrSSLKeyHasWorldPermissions for backwards compatability with
+ // existing code.
+ if err == errSSLKeyHasUnacceptableUserPermissions || err == errSSLKeyHasUnacceptableRootPermissions {
+ err = ErrSSLKeyHasWorldPermissions
}
- return nil
+ return err
+}
+
+// hasCorrectPermissions checks the file info (and the unix-specific stat_t
+// output) to verify that the permissions on the file are correct.
+//
+// If the file is owned by the same user the process is running as,
+// the file should only have 0600 (u=rw). If the file is owned by root,
+// and the group matches the group that the process is running in, the
+// permissions cannot be more than 0640 (u=rw,g=r). The file should
+// never have world permissions.
+//
+// Returns an error when the permission check fails.
+func hasCorrectPermissions(info os.FileInfo) error {
+ // if file's permission matches 0600, allow access.
+ userPermissionMask := (os.FileMode(0777) ^ maxUserOwnedKeyPermissions)
+
+ // regardless of if we're running as root or not, 0600 is acceptable,
+ // so we return if we match the regular user permission mask.
+ if info.Mode().Perm()&userPermissionMask == 0 {
+ return nil
+ }
+
+ // We need to pull the Unix file information to get the file's owner.
+ // If we can't access it, there's some sort of operating system level error
+ // and we should fail rather than attempting to use faulty information.
+ sysInfo := info.Sys()
+ if sysInfo == nil {
+ return ErrSSLKeyUnknownOwnership
+ }
+
+ unixStat, ok := sysInfo.(*syscall.Stat_t)
+ if !ok {
+ return ErrSSLKeyUnknownOwnership
+ }
+
+ // if the file is owned by root, we allow 0640 (u=rw,g=r) to match what
+ // Postgres does.
+ if unixStat.Uid == rootUserID {
+ rootPermissionMask := (os.FileMode(0777) ^ maxRootOwnedKeyPermissions)
+ if info.Mode().Perm()&rootPermissionMask != 0 {
+ return errSSLKeyHasUnacceptableRootPermissions
+ }
+ return nil
+ }
+
+ return errSSLKeyHasUnacceptableUserPermissions
}