-
Notifications
You must be signed in to change notification settings - Fork 913
/
ssl_permissions.go
93 lines (78 loc) · 2.89 KB
/
ssl_permissions.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
//go:build !windows
// +build !windows
package pq
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.
//
// libpq does not check key file permissions on Windows.
func sslKeyPermissions(sslkey string) error {
info, err := os.Stat(sslkey)
if err != nil {
return err
}
err = hasCorrectPermissions(info)
// return ErrSSLKeyHasWorldPermissions for backwards compatability with
// existing code.
if err == errSSLKeyHasUnacceptableUserPermissions || err == errSSLKeyHasUnacceptableRootPermissions {
err = ErrSSLKeyHasWorldPermissions
}
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
}