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 serverlistener 21 22import ( 23 "net" 24 "strings" 25 26 "zabbix.com/internal/agent" 27) 28 29// AllowedPeers is preparsed content of field Server 30type AllowedPeers struct { 31 ips []net.IP 32 nets []*net.IPNet 33 names []string 34} 35 36// GetAllowedPeers is parses the Server field 37func GetAllowedPeers(options *agent.AgentOptions) (allowedPeers *AllowedPeers, err error) { 38 ap := &AllowedPeers{} 39 40 if options.Server != "" { 41 opts := strings.Split(options.Server, ",") 42 for _, o := range opts { 43 peer := strings.Trim(o, " \t") 44 if _, peerNet, err := net.ParseCIDR(peer); nil == err { 45 if ap.isPresent(peerNet) { 46 continue 47 } 48 ap.nets = append(ap.nets, peerNet) 49 maskLeadSize, maskTotalOnes := peerNet.Mask.Size() 50 if 0 == maskLeadSize && 128 == maskTotalOnes { 51 _, peerNet, _ = net.ParseCIDR("0.0.0.0/0") 52 if !ap.isPresent(peerNet) { 53 ap.nets = append(ap.nets, peerNet) 54 } 55 } 56 } else if peerip := net.ParseIP(peer); nil != peerip { 57 if ap.isPresent(peerip) { 58 continue 59 } 60 ap.ips = append(ap.ips, peerip) 61 } else if !ap.isPresent(peer) { 62 ap.names = append(ap.names, peer) 63 } 64 } 65 } 66 67 return ap, nil 68} 69 70// CheckPeer validate incoming connection peer 71func (ap *AllowedPeers) CheckPeer(ip net.IP) bool { 72 if ap.checkNetIP(ip) { 73 return true 74 } 75 76 for _, nameAllowed := range ap.names { 77 if ips, err := net.LookupHost(nameAllowed); nil == err { 78 for _, ipPeer := range ips { 79 ipAllowed := net.ParseIP(ipPeer) 80 if ipAllowed.Equal(ip) { 81 return true 82 } 83 } 84 } 85 } 86 87 return false 88} 89 90func (ap *AllowedPeers) isPresent(value interface{}) bool { 91 switch v := value.(type) { 92 case *net.IPNet: 93 for _, va := range ap.nets { 94 maskLeadSize, _ := va.Mask.Size() 95 maskLeadSizeNew, _ := v.Mask.Size() 96 if maskLeadSize <= maskLeadSizeNew && va.Contains(v.IP) { 97 return true 98 } 99 } 100 case net.IP: 101 if ap.checkNetIP(v) { 102 return true 103 } 104 case string: 105 for _, v := range ap.names { 106 if v == value { 107 return true 108 } 109 } 110 } 111 112 return false 113} 114 115func (ap *AllowedPeers) checkNetIP(ip net.IP) bool { 116 for _, netAllowed := range ap.nets { 117 if netAllowed.Contains(ip) { 118 return true 119 } 120 } 121 for _, ipAllowed := range ap.ips { 122 if ipAllowed.Equal(ip) { 123 return true 124 } 125 } 126 return false 127} 128