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.
42 static void Ban_saveBanFile(void);
43 static void Ban_readBanFile(void);
46 declare_list(banlist);
47 static int bancount; /* = 0 */
48 static int ban_duration;
49 static bool_t banlist_changed;
53 ban_duration = getIntConf(BAN_LENGTH);
54 /* Read ban file here */
55 if (getStrConf(BANFILE) != NULL)
62 if (getStrConf(BANFILE) != NULL)
68 void Ban_UserBan(client_t *client, char *reason)
73 ban = calloc(1, sizeof(ban_t));
75 Log_fatal("Out of memory");
77 memcpy(ban->hash, client->hash, 20);
79 ban->address = client->remote_tcp;
80 ban->mask = (ban->address.ss_family == AF_INET) ? 32 : 128;
81 ban->reason = strdup(reason);
82 ban->name = strdup(client->username);
83 ban->time = time(NULL);
84 ban->duration = ban_duration;
85 Timer_init(&ban->startTime);
86 list_add_tail(&ban->node, &banlist);
88 banlist_changed = true;
89 if(getBoolConf(SYNC_BANFILE))
92 SSLi_hash2hex(ban->hash, hexhash);
94 Log_info_client(client, "User kickbanned. Reason: '%s' Hash: %s IP: %s Banned for: %d seconds",
95 ban->reason, hexhash, Util_clientAddressToString(client), ban->duration);
99 void Ban_pruneBanned()
103 uint64_t bantime_long;
105 list_iterate(itr, &banlist) {
106 ban = list_get_entry(itr, ban_t, node);
107 bantime_long = ban->duration * 1000000LL;
109 SSLi_hash2hex(ban->hash, hexhash);
110 Log_debug("BL: User %s Reason: '%s' Hash: %s IP: %s Time left: %d",
111 ban->name, ban->reason, hexhash, Util_addressToString(&ban->address)),
112 bantime_long / 1000000LL - Timer_elapsed(&ban->startTime) / 1000000LL);
114 /* Duration of 0 = forever */
115 if (ban->duration != 0 && Timer_isElapsed(&ban->startTime, bantime_long)) {
118 list_del(&ban->node);
121 banlist_changed = true;
122 if(getBoolConf(SYNC_BANFILE))
128 bool_t Ban_isBanned(client_t *client)
132 list_iterate(itr, &banlist) {
133 ban = list_get_entry(itr, ban_t, node);
134 if (memcmp(ban->hash, client->hash, 20) == 0)
141 bool_t Ban_isBannedAddr(struct sockaddr_storage *address)
145 char* addressString = Util_addressToString(address);
147 list_iterate(itr, &banlist) {
148 ban = list_get_entry(itr, ban_t, node);
150 if( strncmp(Util_addressToString(&ban->address), addressString, ban->mask) == 0) {
158 int Ban_getBanCount(void)
163 message_t *Ban_getBanList(void)
174 msg = Msg_banList_create(bancount);
175 list_iterate(itr, &banlist) {
176 ban = list_get_entry(itr, ban_t, node);
177 gmtime_r(&ban->time, ×pec);
178 strftime(timestr, 32, "%Y-%m-%dT%H:%M:%S", ×pec);
179 SSLi_hash2hex(ban->hash, hexhash);
180 memset(address, 0, 16);
182 if(ban->address.ss_family == AF_INET) {
183 memcpy(&address[12], &((struct sockaddr_in *)&ban->address)->sin_addr, 4);
184 memset(&address[10], 0xff, 2);
185 Msg_banList_addEntry(msg, i++, address, ban->mask + 96, ban->name, hexhash, ban->reason, timestr, ban->duration);
187 memcpy(&address, &((struct sockaddr_in6 *)&ban->address)->sin6_addr, 16);
188 Msg_banList_addEntry(msg, i++, address, ban->mask, ban->name, hexhash, ban->reason, timestr, ban->duration);
195 void Ban_clearBanList(void)
198 struct dlist *itr, *save;
199 list_iterate_safe(itr, save, &banlist) {
200 ban = list_get_entry(itr, ban_t, node);
203 list_del(&ban->node);
209 void Ban_putBanList(message_t *msg, int n_bans)
214 char *hexhash, *name, *reason, *start;
215 uint32_t duration, mask;
217 char mappedBytes[12] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff};
219 for (i = 0; i < n_bans; i++) {
220 Msg_banList_getEntry(msg, i, &address, &mask, &name, &hexhash, &reason, &start, &duration);
221 ban = malloc(sizeof(ban_t));
223 Log_fatal("Out of memory");
224 SSLi_hex2hash(hexhash, ban->hash);
226 if(memcmp(address, mappedBytes, 12) == 0) {
227 memcpy(&((struct sockaddr_in *)&ban->address)->sin_addr, &address[12], 4);
228 ban->address.ss_family = AF_INET;
233 memcpy(&((struct sockaddr_in6 *)&ban->address)->sin6_addr, address, 16);
234 ban->address.ss_family = AF_INET6;
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);
270 fprintf(file, "%s,%s,%d,%ld,%d,%s,%s\n", hexhash, Util_addressToString(&ban->address),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)
280 char line[1024], *hexhash, *address, *name, *reason;
281 uint32_t mask, duration;
286 file = fopen(getStrConf(BANFILE), "r");
288 Log_warn("Could not read banlist file %s: %s", getStrConf(BANFILE), strerror(errno));
291 while (fgets(line, 1024, file) != NULL) {
292 p = strtok(line, ",");
294 p = strtok(NULL, ",");
295 if (p == NULL) break;
297 p = strtok(NULL, ",");
298 if (p == NULL) break;
299 mask = strtoul(p, NULL, 0);
300 p = strtok(NULL, ",");
301 if (p == NULL) break;
302 time = strtoul(p, NULL, 0);
303 p = strtok(NULL, ",");
304 if (p == NULL) break;
305 duration = strtoul(p, NULL, 0);
306 p = strtok(NULL, ",");
307 if (p == NULL) break;
309 p = strtok(NULL, "\n");
310 if (p == NULL) break;
313 ban = malloc(sizeof(ban_t));
315 Log_fatal("Out of memory");
316 memset(ban, 0, sizeof(ban_t));
317 SSLi_hex2hash(hexhash, ban->hash);
318 if (inet_pton(AF_INET, address, &ban->address) == 0) {
319 if (inet_pton(AF_INET6, address, &ban->address) == 0) {
320 Log_warn("Address \"%s\" is illegal!", address);
322 ban->address.ss_family = AF_INET6;
325 ban->address.ss_family = AF_INET;
327 ban->name = strdup(name);
328 ban->reason = strdup(reason);
329 if (ban->name == NULL || ban->reason == NULL)
330 Log_fatal("Out of memory");
332 ban->duration = duration;
334 ban->startTime = ban->time * 1000000LL;
335 list_add_tail(&ban->node, &banlist);
337 Log_debug("Banfile: H = '%s' A = '%s' M = %d U = '%s' R = '%s'", hexhash, address, ban->mask, ban->name, ban->reason);
340 Log_info("Banlist file '%s': %d entries read", getStrConf(BANFILE), bancount);