1 /* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */
2
3 #include "restrictions.h"
4
5 #include <map>
6 #include <string>
7
8 #include "System/Log/ILog.h"
9 #include "System/Config/ConfigHandler.h"
10
11 #define WILDCARD_HOST "*"
12 #define WILDCARD_PORT -1
13
14 #ifndef TEST
15 #define LOG_SECTION_LUASOCKET "LuaSocket"
16 LOG_REGISTER_SECTION_GLOBAL(LOG_SECTION_LUASOCKET)
17 #ifdef LOG_SECTION_CURRENT
18 #undef LOG_SECTION_CURRENT
19 #endif
20 #define LOG_SECTION_CURRENT LOG_SECTION_LUASOCKET
21
22 CONFIG(std::string, TCPAllowConnect).defaultValue(WILDCARD_HOST).readOnly(true);
23 CONFIG(std::string, TCPAllowListen).defaultValue(WILDCARD_HOST).readOnly(true);
24 CONFIG(std::string, UDPAllowConnect).defaultValue("").readOnly(true);
25 CONFIG(std::string, UDPAllowListen).defaultValue(WILDCARD_HOST).readOnly(true);
26 #endif
27
28 CLuaSocketRestrictions* luaSocketRestrictions=0;
29
CLuaSocketRestrictions()30 CLuaSocketRestrictions::CLuaSocketRestrictions()
31 {
32 #ifndef TEST
33 addRules(TCP_CONNECT, configHandler->GetString("TCPAllowConnect"));
34 addRules(TCP_LISTEN, configHandler->GetString("TCPAllowListen"));
35 addRules(UDP_CONNECT, configHandler->GetString("UDPAllowConnect"));
36 addRules(UDP_LISTEN, configHandler->GetString("UDPAllowListen"));
37 #endif
38 }
39
addRule(RestrictType type,const std::string & hostname,int port,bool allowed)40 void CLuaSocketRestrictions::addRule(RestrictType type, const std::string& hostname, int port, bool allowed)
41 {
42 if ((port != WILDCARD_PORT) && ((port<=0) || (port>65535))){
43 LOG_L(L_ERROR, "Invalid port specified: %d", port);
44 return;
45 }
46 const TSocketRule* rule = getRule(type, hostname.c_str(), port);
47 if ((rule != NULL) && (rule->allowed == allowed)) {
48 LOG_L(L_ERROR, "Rule already exists: %s %d", hostname.c_str(), port);
49 return;
50 }
51
52 if (!allowed) { //add deny rules to the front of the list
53 restrictions[type].push_front(TSocketRule(hostname, port, allowed));
54 } else {
55 restrictions[type].push_back(TSocketRule(hostname, port, allowed));
56 }
57 }
58
addRule(RestrictType type,const std::string & rule)59 void CLuaSocketRestrictions::addRule(RestrictType type, const std::string& rule)
60 {
61 if (rule == WILDCARD_HOST) { //allow everything
62 restrictions[type].push_back(TSocketRule(WILDCARD_HOST, WILDCARD_PORT, true));
63 return;
64 }
65
66 size_t delimpos = rule.find(":");
67 if (delimpos==std::string::npos) {
68 LOG_L(L_ERROR, "Invalid %d rule: %s, rule has to be hostname:port", type, rule.c_str());
69 return;
70 }
71 const std::string strport = rule.substr(delimpos+1, delimpos-rule.length());
72 const int port = atoi(strport.c_str());
73 addRule(type, rule.substr(0, delimpos), port, true);
74 }
75
addRules(RestrictType type,const std::string & configstr)76 void CLuaSocketRestrictions::addRules(RestrictType type, const std::string& configstr)
77 {
78 std::string rule;
79
80 for(int i=0; i < configstr.length(); i++) {
81 const char ch = configstr[i];
82 if ((isspace(ch)) && (!rule.empty())) {
83 addRule(type, rule);
84 rule = "";
85 } else {
86 rule += ch;
87 }
88 }
89 if (!rule.empty()) {
90 addRule(type, rule);
91 }
92 }
93
94 /*
95 bool isValidIpAddress(char *ipAddress)
96 {
97 struct sockaddr_in sa;
98 int result = inet_pton(AF_INET, ipAddress, &(sa.sin_addr));
99 return result != 0;
100 }
101 */
102
isAllowed(RestrictType type,const char * hostname,int port)103 bool CLuaSocketRestrictions::isAllowed(RestrictType type, const char* hostname, int port) {
104 const TSocketRule* rule = getRule(type, hostname, port);
105 if (rule==NULL) {
106 return false;
107 }
108 return rule->allowed;
109 }
110
getRule(RestrictType type,const char * hostname,int port)111 const TSocketRule* CLuaSocketRestrictions::getRule(RestrictType type, const char* hostname, int port) {
112 {
113 int start, end;
114 if (type != ALL_RULES) {
115 start = type;
116 end = start+1;
117 } else {
118 start = 0;
119 end = ALL_RULES;
120 }
121 for (int i=start; i<end; i++) {
122 std::list<TSocketRule>::iterator it;
123 for(it = restrictions[i].begin(); it != restrictions[i].end(); ++it) {
124 const TSocketRule& rule = *it;
125 if ((hostname == rule.hostname) || (rule.hostname == WILDCARD_HOST)) {
126 if ((rule.port == WILDCARD_PORT) || (rule.port == port)) {
127 return &rule;
128 }
129 }
130 }
131 }
132 return NULL;
133 }
134 }
135
addIP(const char * hostname,const char * ip)136 void CLuaSocketRestrictions::addIP(const char* hostname, const char* ip)
137 {
138 for(int i=0; i<ALL_RULES; i++) {
139 std::list<TSocketRule>::iterator it;
140 for(it = restrictions[i].begin(); it != restrictions[i].end(); ++it) {
141 const TSocketRule &rule = *it;
142 if ((rule.hostname == hostname) && (getRule((RestrictType)i, ip, rule.port) == NULL)) { //add rule with ip, when not exisitng
143 addRule((RestrictType)i, ip, rule.port, rule.allowed);
144 }
145 }
146 }
147 }
148
ruleToStr(RestrictType type)149 const char* CLuaSocketRestrictions::ruleToStr(RestrictType type) {
150 switch(type) {
151 case TCP_CONNECT:
152 return "TCP_CONNECT";
153 case TCP_LISTEN:
154 return "TCP_LISTEN ";
155 case UDP_LISTEN:
156 return "UDP_LISTEN ";
157 case UDP_CONNECT:
158 return "UDP_CONNECT";
159 default:
160 return "INVALID";
161 }
162 }
163
~CLuaSocketRestrictions()164 CLuaSocketRestrictions::~CLuaSocketRestrictions()
165 {
166 LOG("Dumping luasocket rules:");
167 for(int i=0; i<ALL_RULES; i++) {
168 std::list<TSocketRule>::iterator it;
169 for(it = restrictions[i].begin(); it != restrictions[i].end(); ++it) {
170 TSocketRule &rule = *it;
171 LOG("%s %s %s %d", ruleToStr((RestrictType)i), rule.allowed ? "ALLOW" : "DENY ", rule.hostname.c_str(), rule.port);
172 }
173 }
174 }
175
176