-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcommon.go
204 lines (174 loc) · 5.45 KB
/
common.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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
package main
import (
"errors"
"fmt"
"net"
"os"
"regexp"
"kernel.org/pub/linux/libs/security/libcap/cap"
)
// settings
var (
// Generic IPv4 ip_forward setting path
ipv4FPath = "/proc/sys/net/ipv4/ip_forward"
// IPv6 forwarding for all interfaces setting path
ipv6FPath = "/proc/sys/net/ipv6/conf/all/forwarding"
)
// iota constants
type (
hostType byte // host type
ipFwd byte // system IP forwarding state
)
const (
hostTypeUnknown hostType = iota // undefined
hostTypeIPv4 // host in IPv4 format
hostTypeIPv6 // host in IPv6 format
hostTypeFqdn // host in FQDN format
)
const (
ipFwdUnknown ipFwd = iota // undefined
ipFwdNone // no IP forwarding
ipFwdAll // IP forwarding enabled for IPv4 and IPv6
ipFwdV4Only // IP forwarding enabled for IPv4
ipFwdV6Only // IP forwarding enabled for IPv6
)
// Lookup patterns
const (
// FQDN regex string according to RFC 1123
fqdnRegexStringRFC1123 = `^([a-zA-Z0-9]{1}[a-zA-Z0-9-]{0,62})(\.[a-zA-Z0-9]{1}[a-zA-Z0-9-]{0,62})*?(\.[a-zA-Z]{1}[a-zA-Z0-9]{0,62})\.?$` // same as hostnameRegexStringRFC1123 but must contain a non numerical TLD (possibly ending with '.')
)
// Pattern matches
var (
// parses the fqdnRegexStringRFC1123 regex
fqdnRegexRFC1123 = regexp.MustCompile(fqdnRegexStringRFC1123)
)
// Common errors
var (
errCheckIpFwd = errors.New(
"IP Forwarding check failed",
)
errReadIpv4Sett = errors.New(
"Couldn't read IPv4 forwarding control file",
)
errReadIpv6Sett = errors.New(
"Couldn't read IPv6 forwarding control file",
)
errCheckCap = errors.New(
"capabilities check failed",
)
errHostType = errors.New(
"host type not found",
)
)
// Linux capabilities are a method to assign specific privileges to a running process
// This function checks if a Linux capability is set for a given process
// An error is returned in case it is not possible to perform the check or in case the capability check fails
func checkCapabilities(cs *cap.Set, vec cap.Flag, val cap.Value) error {
// check for process cs if val capabilities has the vec flags set
cf, err := cs.GetFlag(vec, val)
if err != nil {
return fmt.Errorf("%w: %w", errCheckCap, err)
}
if !cf {
LogDVf("Check capabilities: failed")
return fmt.Errorf(
"%w: '%s' flag not set on '%s' capability",
errCheckCap,
vec,
val,
)
}
LogDVf("Check capabilities: succeeded")
return nil
}
// checkIpFwd checks if IP forwarding is system enabled
// /proc/sys/net/ipv4/ip_forward is checked for IPv4
// /proc/sys/net/ipv6/conf/all/forwarding for IPv6
// IP forwarding is not checked for individual interfaces
// It is only checked if IP forwarding is generically enabled
// The function returns ipFwdUnkown in case of error
// An error is returned if the config files can't be read
// It returns:
// - ipFwdNone when IP forwarding is not enabled for IPv4 or IPv6
// - ipFwdAll when IP forwading is enabled for IPv4 and IPv6
// - ipFwdV4Only when IP forwarding is enabled for IPv4, but not for IPv6
// - ipFwdV6Only when IP forwarding is not enabled for IPv4, but is enabled for IPv6
func checkIpFwd() (ipFwd, error) {
LogDf("IP Fwd check: checking '%s' for IPv4 IP Forwarding", ipv4FPath)
ipv4f, err := os.ReadFile(ipv4FPath)
if err != nil {
return ipFwdUnknown, fmt.Errorf("%w: %w", errCheckIpFwd, errReadIpv4Sett)
}
LogDf("IP Fwd check: checking '%s' for IPv6 IP Forwarding", ipv6FPath)
ipv6f, err := os.ReadFile(ipv6FPath)
if err != nil {
return ipFwdUnknown, fmt.Errorf("%w: %w", errCheckIpFwd, errReadIpv6Sett)
}
// byte 49 is ASCII '1'
// file has content 0 when disabled
// file has content 1 when enabled
oneAscii := 49
enabled := byte(oneAscii)
if ipv4f[0] != enabled {
LogDf("IP Fwd check: IPv4 Forwarding is not enabled for all interfaces")
if ipv6f[0] != enabled {
LogDf("IP Fwd check: IPv6 Forwarding is not enabled for all interfaces")
return ipFwdNone, nil
} else {
LogDf("IP Fwd check: IPv6 Forwarding is enabled for all interfaces")
return ipFwdV6Only, nil
}
}
LogDf("IP Fwd check: IPv4 Forwarding is enabled for all interfaces")
if ipv6f[0] != enabled {
LogDf("IP Fwd check: IPv6 Forwarding is not enabled for all interfaces")
return ipFwdV4Only, nil
}
LogDf("IP Fwd check: IPv6 Forwarding is enabled for all interfaces")
return ipFwdAll, nil
}
// getHostType returns a hostType from input string
func getHostType(host string) (hostType, error) {
ip := net.ParseIP(host)
if ip != nil {
if ip.To4() != nil {
return hostTypeIPv4, nil
} else if ip.To16() != nil {
return hostTypeIPv6, nil
}
}
if isFqdn(host) {
return hostTypeFqdn, nil
}
return hostTypeUnknown, fmt.Errorf("'%s' '%w'", host, errHostType)
}
// isFqdn checks if input string is FQDN and returns boolean result
func isFqdn(s string) bool {
return fqdnRegexRFC1123.MatchString(s)
}
// findUniqueNetIp returns a list of unique net.IP
func findUniqueNetIp(nipl *[]net.IP) []net.IP {
unipl := make([]net.IP, 0)
niplLoop:
for _, nip := range *nipl {
for _, uip := range unipl {
if uip.Equal(nip) {
continue niplLoop
}
}
unipl = append(unipl, nip)
}
return unipl
}
// findDuplicateNetIp returns a list of duplicate net.IP
func findDuplicateNetIp(nipl *[]net.IP) []net.IP {
dnipl := make([]net.IP, 0)
occurrenceCount := make(map[string]int)
for _, nip := range *nipl {
occurrenceCount[nip.String()]++
if occurrenceCount[nip.String()] == 2 {
dnipl = append(dnipl, nip)
}
}
return dnipl
}