1 /*
2  * InspIRCd -- Internet Relay Chat Daemon
3  *
4  *   Copyright (C) 2013, 2017 Sadie Powell <sadie@witchery.services>
5  *   Copyright (C) 2012 Robby <robby@chatbelgie.be>
6  *   Copyright (C) 2009 Uli Schlachter <psychon@inspircd.org>
7  *   Copyright (C) 2008, 2010 Craig Edwards <brain@inspircd.org>
8  *   Copyright (C) 2007-2008 Robin Burchell <robin+git@viroteck.net>
9  *   Copyright (C) 2007-2008 Dennis Friis <peavey@inspircd.org>
10  *
11  * This file is part of InspIRCd.  InspIRCd is free software: you can
12  * redistribute it and/or modify it under the terms of the GNU General Public
13  * License as published by the Free Software Foundation, version 2.
14  *
15  * This program is distributed in the hope that it will be useful, but WITHOUT
16  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
22  */
23 
24 
25 #include "inspircd.h"
26 
MatchInternal(const unsigned char * str,const unsigned char * mask,unsigned const char * map)27 static bool MatchInternal(const unsigned char* str, const unsigned char* mask, unsigned const char* map)
28 {
29 	unsigned char* cp = NULL;
30 	unsigned char* mp = NULL;
31 	unsigned char* string = (unsigned char*)str;
32 	unsigned char* wild = (unsigned char*)mask;
33 
34 	while ((*string) && (*wild != '*'))
35 	{
36 		if ((map[*wild] != map[*string]) && (*wild != '?'))
37 		{
38 			return 0;
39 		}
40 		wild++;
41 		string++;
42 	}
43 
44 	while (*string)
45 	{
46 		if (*wild == '*')
47 		{
48 			if (!*++wild)
49 			{
50 				return 1;
51 			}
52 			mp = wild;
53 			cp = string+1;
54 		}
55 		else
56 			if ((map[*wild] == map[*string]) || (*wild == '?'))
57 			{
58 				wild++;
59 				string++;
60 			}
61 			else
62 			{
63 				wild = mp;
64 				string = cp++;
65 			}
66 
67 	}
68 
69 	while (*wild == '*')
70 	{
71 		wild++;
72 	}
73 
74 	return !*wild;
75 }
76 
77 // Below here is all wrappers around MatchInternal
78 
Match(const std::string & str,const std::string & mask,unsigned const char * map)79 bool InspIRCd::Match(const std::string& str, const std::string& mask, unsigned const char* map)
80 {
81 	if (!map)
82 		map = national_case_insensitive_map;
83 
84 	return MatchInternal((const unsigned char*)str.c_str(), (const unsigned char*)mask.c_str(), map);
85 }
86 
Match(const char * str,const char * mask,unsigned const char * map)87 bool InspIRCd::Match(const char* str, const char* mask, unsigned const char* map)
88 {
89 	if (!map)
90 		map = national_case_insensitive_map;
91 
92 	return MatchInternal((const unsigned char*)str, (const unsigned char*)mask, map);
93 }
94 
MatchCIDR(const std::string & str,const std::string & mask,unsigned const char * map)95 bool InspIRCd::MatchCIDR(const std::string& str, const std::string& mask, unsigned const char* map)
96 {
97 	if (irc::sockets::MatchCIDR(str, mask, true))
98 		return true;
99 
100 	// Fall back to regular match
101 	return InspIRCd::Match(str, mask, map);
102 }
103 
MatchCIDR(const char * str,const char * mask,unsigned const char * map)104 bool InspIRCd::MatchCIDR(const char* str, const char* mask, unsigned const char* map)
105 {
106 	if (irc::sockets::MatchCIDR(str, mask, true))
107 		return true;
108 
109 	// Fall back to regular match
110 	return InspIRCd::Match(str, mask, map);
111 }
112 
MatchMask(const std::string & masks,const std::string & hostname,const std::string & ipaddr)113 bool InspIRCd::MatchMask(const std::string& masks, const std::string& hostname, const std::string& ipaddr)
114 {
115 	irc::spacesepstream masklist(masks);
116 	std::string mask;
117 	while (masklist.GetToken(mask))
118 	{
119 		if (InspIRCd::Match(hostname, mask, ascii_case_insensitive_map) ||
120 			InspIRCd::MatchCIDR(ipaddr, mask, ascii_case_insensitive_map))
121 		{
122 			return true;
123 		}
124 	}
125 	return false;
126 }
127