1/* 2** Zabbix 3** Copyright (C) 2001-2021 Zabbix SIA 4** 5** This program is free software; you can redistribute it and/or modify 6** it under the terms of the GNU General Public License as published by 7** the Free Software Foundation; either version 2 of the License, or 8** (at your option) any later version. 9** 10** This program is distributed in the hope that it will be useful, 11** but WITHOUT ANY WARRANTY; without even the implied warranty of 12** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13** GNU General Public License for more details. 14** 15** You should have received a copy of the GNU General Public License 16** along with this program; if not, write to the Free Software 17** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18**/ 19 20package zbxnet 21 22import ( 23 "net" 24 "strings" 25) 26 27// AllowedPeers is preparsed content of field Server 28type AllowedPeers struct { 29 ips []net.IP 30 nets []*net.IPNet 31 names []string 32} 33 34// GetAllowedPeers is parses the Server field 35func GetAllowedPeers(servers string) (allowedPeers *AllowedPeers, err error) { 36 ap := &AllowedPeers{} 37 38 if servers != "" { 39 opts := strings.Split(servers, ",") 40 for _, o := range opts { 41 peer := strings.Trim(o, " \t") 42 if _, peerNet, err := net.ParseCIDR(peer); nil == err { 43 if ap.isPresent(peerNet) { 44 continue 45 } 46 ap.nets = append(ap.nets, peerNet) 47 maskLeadSize, maskTotalOnes := peerNet.Mask.Size() 48 if 0 == maskLeadSize && 128 == maskTotalOnes { 49 _, peerNet, _ = net.ParseCIDR("0.0.0.0/0") 50 if !ap.isPresent(peerNet) { 51 ap.nets = append(ap.nets, peerNet) 52 } 53 } 54 } else if peerip := net.ParseIP(peer); nil != peerip { 55 if ap.isPresent(peerip) { 56 continue 57 } 58 ap.ips = append(ap.ips, peerip) 59 } else if !ap.isPresent(peer) { 60 ap.names = append(ap.names, peer) 61 } 62 } 63 } 64 65 return ap, nil 66} 67 68// CheckPeer validate incoming connection peer 69func (ap *AllowedPeers) CheckPeer(ip net.IP) bool { 70 if ap.checkNetIP(ip) { 71 return true 72 } 73 74 for _, nameAllowed := range ap.names { 75 if ips, err := net.LookupHost(nameAllowed); nil == err { 76 for _, ipPeer := range ips { 77 ipAllowed := net.ParseIP(ipPeer) 78 if ipAllowed.Equal(ip) { 79 return true 80 } 81 } 82 } 83 } 84 85 return false 86} 87 88func (ap *AllowedPeers) isPresent(value interface{}) bool { 89 switch v := value.(type) { 90 case *net.IPNet: 91 for _, va := range ap.nets { 92 maskLeadSize, _ := va.Mask.Size() 93 maskLeadSizeNew, _ := v.Mask.Size() 94 if maskLeadSize <= maskLeadSizeNew && va.Contains(v.IP) { 95 return true 96 } 97 } 98 case net.IP: 99 if ap.checkNetIP(v) { 100 return true 101 } 102 case string: 103 for _, v := range ap.names { 104 if v == value { 105 return true 106 } 107 } 108 } 109 110 return false 111} 112 113func (ap *AllowedPeers) checkNetIP(ip net.IP) bool { 114 for _, netAllowed := range ap.nets { 115 if netAllowed.Contains(ip) { 116 return true 117 } 118 } 119 for _, ipAllowed := range ap.ips { 120 if ipAllowed.Equal(ip) { 121 return true 122 } 123 } 124 return false 125} 126