forked from cloudflare/cfssl
-
Notifications
You must be signed in to change notification settings - Fork 0
/
whitelist_net.go
170 lines (142 loc) · 4.13 KB
/
whitelist_net.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
package whitelist
// This file contains a variant of the ACL that operates on
// netblocks. It will mimic as much of the code in whitelist.go
// that is needed to support network whitelists.
import (
"errors"
"log"
"net"
"strings"
"sync"
)
// A NetACL stores a list of permitted IP networks.
type NetACL interface {
ACL
// Add takes an IP network and adds it to the whitelist so
// that it is now permitted.
Add(*net.IPNet)
// Remove takes an IP network and drops it from the whitelist
// so that it is no longer permitted.
Remove(*net.IPNet)
}
// BasicNet implements a basic map-backed network whitelist using
// locks for concurrency. It must be initialised with one of the
// constructor functions. This particular implementation is
// unoptimised and will not scale.
type BasicNet struct {
lock *sync.Mutex
whitelist []*net.IPNet
}
// Permitted returns true if the IP has been whitelisted.
func (wl *BasicNet) Permitted(ip net.IP) bool {
if !validIP(ip) { // see whitelist.go for this function
return false
}
wl.lock.Lock()
defer wl.lock.Unlock()
for i := range wl.whitelist {
if wl.whitelist[i].Contains(ip) {
return true
}
}
return false
}
// BUG(kyle): overlapping networks aren't detected.
// Add adds a new network to the whitelist. Caveat: overlapping
// networks won't be detected.
func (wl *BasicNet) Add(n *net.IPNet) {
if n == nil {
return
}
wl.lock.Lock()
defer wl.lock.Unlock()
wl.whitelist = append(wl.whitelist, n)
}
// Remove removes a network from the whitelist.
func (wl *BasicNet) Remove(n *net.IPNet) {
if n == nil {
return
}
index := -1
wl.lock.Lock()
defer wl.lock.Unlock()
for i := range wl.whitelist {
if wl.whitelist[i].String() == n.String() {
index = i
break
}
}
if index == -1 {
return
}
wl.whitelist = append(wl.whitelist[:index], wl.whitelist[index+1:]...)
}
// NewBasicNet constructs a new basic network-based whitelist.
func NewBasicNet() *BasicNet {
return &BasicNet{
lock: new(sync.Mutex),
}
}
// MarshalJSON serialises a network whitelist to a comma-separated
// list of networks.
func (wl *BasicNet) MarshalJSON() ([]byte, error) {
var ss = make([]string, 0, len(wl.whitelist))
for i := range wl.whitelist {
ss = append(ss, wl.whitelist[i].String())
}
out := []byte(`"` + strings.Join(ss, ",") + `"`)
return out, nil
}
// UnmarshalJSON implements the json.Unmarshaler interface for network
// whitelists, taking a comma-separated string of networks.
func (wl *BasicNet) UnmarshalJSON(in []byte) error {
if in[0] != '"' || in[len(in)-1] != '"' {
return errors.New("whitelist: invalid whitelist")
}
if wl.lock == nil {
wl.lock = new(sync.Mutex)
}
wl.lock.Lock()
defer wl.lock.Unlock()
var err error
netString := strings.TrimSpace(string(in[1 : len(in)-1]))
nets := strings.Split(netString, ",")
wl.whitelist = make([]*net.IPNet, len(nets))
for i := range nets {
addr := strings.TrimSpace(nets[i])
if addr == "" {
continue
}
_, wl.whitelist[i], err = net.ParseCIDR(addr)
if err != nil {
wl.whitelist = nil
return err
}
}
return nil
}
// NetStub allows network whitelisting to be added into a system's
// flow without doing anything yet. All operations result in warning
// log messages being printed to stderr. There is no mechanism for
// squelching these messages short of modifying the log package's
// default logger.
type NetStub struct{}
// Permitted always returns true, but prints a warning message alerting
// that whitelisting is stubbed.
func (wl NetStub) Permitted(ip net.IP) bool {
log.Printf("WARNING: whitelist check for %s but whitelisting is stubbed", ip)
return true
}
// Add prints a warning message about whitelisting being stubbed.
func (wl NetStub) Add(ip *net.IPNet) {
log.Printf("WARNING: IP network %s added to whitelist but whitelisting is stubbed", ip)
}
// Remove prints a warning message about whitelisting being stubbed.
func (wl NetStub) Remove(ip *net.IPNet) {
log.Printf("WARNING: IP network %s removed from whitelist but whitelisting is stubbed", ip)
}
// NewNetStub returns a new stubbed network whitelister.
func NewNetStub() NetStub {
log.Println("WARNING: whitelisting is being stubbed")
return NetStub{}
}