1 /* Copyright (C) 2009-2014, Martin Johansson <martin@fatbob.nu>
2 Copyright (C) 2005-2014, Thorvald Natvig <thorvald@natvig.com>
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions
10 - Redistributions of source code must retain the above copyright notice,
11 this list of conditions and the following disclaimer.
12 - Redistributions in binary form must reproduce the above copyright notice,
13 this list of conditions and the following disclaimer in the documentation
14 and/or other materials provided with the distribution.
15 - Neither the name of the Developers nor the names of its contributors may
16 be used to endorse or promote products derived from this software without
17 specific prior written permission.
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
23 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 static void Ban_saveBanFile(void);
41 static void Ban_readBanFile(void);
44 declare_list(banlist);
45 static int bancount; /* = 0 */
46 static int ban_duration;
47 static bool_t banlist_changed;
51 ban_duration = getIntConf(BAN_LENGTH);
52 /* Read ban file here */
53 if (getStrConf(BANFILE) != NULL)
60 if (getStrConf(BANFILE) != NULL)
66 void Ban_UserBan(client_t *client, char *reason)
71 ban = malloc(sizeof(ban_t));
73 Log_fatal("Out of memory");
74 memset(ban, 0, sizeof(ban_t));
76 memcpy(ban->hash, client->hash, 20);
77 if (client->remote_tcp.ss_family == AF_INET) {
78 memcpy(&ban->address, &(((struct sockaddr_in*)&client->remote_tcp)->sin_addr), sizeof(in_addr_t));
79 ban->mask = sizeof(in_addr_t);
81 memcpy(&ban->address, &(((struct sockaddr_in6*)&client->remote_tcp)->sin6_addr), 4 * sizeof(in_addr_t));
82 ban->mask = 4 * sizeof(in_addr_t);
84 ban->reason = strdup(reason);
85 ban->name = strdup(client->username);
86 ban->time = time(NULL);
87 ban->duration = ban_duration;
88 Timer_init(&ban->startTime);
89 list_add_tail(&ban->node, &banlist);
91 banlist_changed = true;
92 if(getBoolConf(SYNC_BANFILE))
95 SSLi_hash2hex(ban->hash, hexhash);
97 char addressPresentation[INET6_ADDRSTRLEN];
99 if(client->remote_tcp.ss_family == AF_INET)
100 inet_ntop(AF_INET, &((struct sockaddr_in*)&client->remote_tcp)->sin_addr, addressPresentation, INET6_ADDRSTRLEN);
102 inet_ntop(AF_INET6, &((struct sockaddr_in6*)&client->remote_tcp)->sin6_addr, addressPresentation, INET6_ADDRSTRLEN);
104 Log_info_client(client, "User kickbanned. Reason: '%s' Hash: %s IP: %s Banned for: %d seconds",
105 ban->reason, hexhash, addressPresentation, ban->duration);
109 void Ban_pruneBanned()
114 uint64_t bantime_long;
116 list_iterate(itr, &banlist) {
117 ban = list_get_entry(itr, ban_t, node);
118 bantime_long = ban->duration * 1000000LL;
120 SSLi_hash2hex(ban->hash, hexhash);
121 Log_debug("BL: User %s Reason: '%s' Hash: %s IP: %s Time left: %d",
122 ban->name, ban->reason, hexhash, inet_ntoa(*((struct in_addr *)&ban->address)),
123 bantime_long / 1000000LL - Timer_elapsed(&ban->startTime) / 1000000LL);
125 /* Duration of 0 = forever */
126 if (ban->duration != 0 && Timer_isElapsed(&ban->startTime, bantime_long)) {
129 list_del(&ban->node);
132 banlist_changed = true;
133 if(getBoolConf(SYNC_BANFILE))
139 bool_t Ban_isBanned(client_t *client)
143 list_iterate(itr, &banlist) {
144 ban = list_get_entry(itr, ban_t, node);
145 if (memcmp(ban->hash, client->hash, 20) == 0)
152 bool_t Ban_isBannedAddr(in_addr_t *addr)
157 in_addr_t tempaddr1, tempaddr2;
159 list_iterate(itr, &banlist) {
160 ban = list_get_entry(itr, ban_t, node);
161 mask = ban->mask - 96;
162 if (mask < 32) { /* XXX - only ipv4 support */
163 memcpy(&tempaddr1, addr, sizeof(in_addr_t));
164 memcpy(&tempaddr2, &ban->address, sizeof(in_addr_t));
165 tempaddr1 &= (2 ^ mask) - 1;
166 tempaddr2 &= (2 ^ mask) - 1;
168 if (memcmp(&tempaddr1, &tempaddr2, sizeof(in_addr_t)) == 0)
174 int Ban_getBanCount(void)
179 message_t *Ban_getBanList(void)
190 msg = Msg_banList_create(bancount);
191 list_iterate(itr, &banlist) {
192 ban = list_get_entry(itr, ban_t, node);
193 gmtime_r(&ban->time, ×pec);
194 strftime(timestr, 32, "%Y-%m-%dT%H:%M:%S", ×pec);
195 SSLi_hash2hex(ban->hash, hexhash);
196 /* ipv4 representation as ipv6 address. */
197 memset(address, 0, 16);
198 memcpy(&address[12], &ban->address, 4);
199 memset(&address[10], 0xff, 2); /* IPv4 */
200 Msg_banList_addEntry(msg, i++, address, ban->mask, ban->name,
201 hexhash, ban->reason, timestr, ban->duration);
206 void Ban_clearBanList(void)
209 struct dlist *itr, *save;
210 list_iterate_safe(itr, save, &banlist) {
211 ban = list_get_entry(itr, ban_t, node);
214 list_del(&ban->node);
220 void Ban_putBanList(message_t *msg, int n_bans)
225 char *hexhash, *name, *reason, *start;
226 uint32_t duration, mask;
229 for (i = 0; i < n_bans; i++) {
230 Msg_banList_getEntry(msg, i, &address, &mask, &name, &hexhash, &reason, &start, &duration);
231 ban = malloc(sizeof(ban_t));
233 Log_fatal("Out of memory");
234 memset(ban, 0, sizeof(ban_t));
235 SSLi_hex2hash(hexhash, ban->hash);
236 memcpy(&ban->address, &address[12], 4);
238 ban->reason = strdup(reason);
239 ban->name = strdup(name);
240 strptime(start, "%Y-%m-%dT%H:%M:%S", ×pec);
241 ban->time = mktime(×pec);
242 ban->startTime = ban->time * 1000000LL;
243 ban->duration = duration;
244 list_add_tail(&ban->node, &banlist);
247 banlist_changed = true;
248 if(getBoolConf(SYNC_BANFILE))
252 static void Ban_saveBanFile(void)
259 if (!banlist_changed)
261 file = fopen(getStrConf(BANFILE), "w");
263 Log_warn("Could not save banlist to file %s: %s", getStrConf(BANFILE), strerror(errno));
266 list_iterate(itr, &banlist) {
267 ban = list_get_entry(itr, ban_t, node);
268 SSLi_hash2hex(ban->hash, hexhash);
269 fprintf(file, "%s,%s,%d,%ld,%d,%s,%s\n", hexhash, inet_ntoa(*((struct in_addr *)&ban->address)),
270 ban->mask, (long int)ban->time, ban->duration, ban->name, ban->reason);
273 banlist_changed = false;
274 Log_info("Banlist file '%s': %d entries written", getStrConf(BANFILE), bancount);
277 static void Ban_readBanFile(void)
281 char line[1024], *hexhash, *address, *name, *reason;
282 uint32_t mask, duration;
287 file = fopen(getStrConf(BANFILE), "r");
289 Log_warn("Could not read banlist file %s: %s", getStrConf(BANFILE), strerror(errno));
292 while (fgets(line, 1024, file) != NULL) {
293 p = strtok(line, ",");
295 p = strtok(NULL, ",");
296 if (p == NULL) break;
298 p = strtok(NULL, ",");
299 if (p == NULL) break;
300 mask = strtoul(p, NULL, 0);
301 p = strtok(NULL, ",");
302 if (p == NULL) break;
303 time = strtoul(p, NULL, 0);
304 p = strtok(NULL, ",");
305 if (p == NULL) break;
306 duration = strtoul(p, NULL, 0);
307 p = strtok(NULL, ",");
308 if (p == NULL) break;
310 p = strtok(NULL, "\n");
311 if (p == NULL) break;
314 ban = malloc(sizeof(ban_t));
316 Log_fatal("Out of memory");
317 memset(ban, 0, sizeof(ban_t));
318 SSLi_hex2hash(hexhash, ban->hash);
319 inet_aton(address, (struct in_addr *)&ban->address);
320 ban->name = strdup(name);
321 ban->reason = strdup(reason);
322 if (ban->name == NULL || ban->reason == NULL)
323 Log_fatal("Out of memory");
325 ban->duration = duration;
327 ban->startTime = ban->time * 1000000LL;
328 list_add_tail(&ban->node, &banlist);
330 Log_debug("Banfile: H = '%s' A = '%s' M = %d U = '%s' R = '%s'", hexhash, address, ban->mask, ban->name, ban->reason);
333 Log_info("Banlist file '%s': %d entries read", getStrConf(BANFILE), bancount);