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 memcpy(&ban->address, &client->remote_tcp.sin_addr, sizeof(in_addr_t));
79 ban->reason = strdup(reason);
80 ban->name = strdup(client->username);
81 ban->time = time(NULL);
82 ban->duration = ban_duration;
83 Timer_init(&ban->startTime);
84 list_add_tail(&ban->node, &banlist);
86 banlist_changed = true;
87 if(getBoolConf(SYNC_BANFILE))
90 SSLi_hash2hex(ban->hash, hexhash);
91 Log_info_client(client, "User kickbanned. Reason: '%s' Hash: %s IP: %s Banned for: %d seconds",
92 ban->reason, hexhash, inet_ntoa(*((struct in_addr *)&ban->address)), ban->duration);
96 void Ban_pruneBanned()
101 uint64_t bantime_long;
103 list_iterate(itr, &banlist) {
104 ban = list_get_entry(itr, ban_t, node);
105 bantime_long = ban->duration * 1000000LL;
107 SSLi_hash2hex(ban->hash, hexhash);
108 Log_debug("BL: User %s Reason: '%s' Hash: %s IP: %s Time left: %d",
109 ban->name, ban->reason, hexhash, inet_ntoa(*((struct in_addr *)&ban->address)),
110 bantime_long / 1000000LL - Timer_elapsed(&ban->startTime) / 1000000LL);
112 /* Duration of 0 = forever */
113 if (ban->duration != 0 && Timer_isElapsed(&ban->startTime, bantime_long)) {
116 list_del(&ban->node);
119 banlist_changed = true;
120 if(getBoolConf(SYNC_BANFILE))
126 bool_t Ban_isBanned(client_t *client)
130 list_iterate(itr, &banlist) {
131 ban = list_get_entry(itr, ban_t, node);
132 if (memcmp(ban->hash, client->hash, 20) == 0)
139 bool_t Ban_isBannedAddr(in_addr_t *addr)
144 in_addr_t tempaddr1, tempaddr2;
146 list_iterate(itr, &banlist) {
147 ban = list_get_entry(itr, ban_t, node);
148 mask = ban->mask - 96;
149 if (mask < 32) { /* XXX - only ipv4 support */
150 memcpy(&tempaddr1, addr, sizeof(in_addr_t));
151 memcpy(&tempaddr2, &ban->address, sizeof(in_addr_t));
152 tempaddr1 &= (2 ^ mask) - 1;
153 tempaddr2 &= (2 ^ mask) - 1;
155 if (memcmp(&tempaddr1, &tempaddr2, sizeof(in_addr_t)) == 0)
161 int Ban_getBanCount(void)
166 message_t *Ban_getBanList(void)
177 msg = Msg_banList_create(bancount);
178 list_iterate(itr, &banlist) {
179 ban = list_get_entry(itr, ban_t, node);
180 gmtime_r(&ban->time, ×pec);
181 strftime(timestr, 32, "%Y-%m-%dT%H:%M:%S", ×pec);
182 SSLi_hash2hex(ban->hash, hexhash);
183 /* ipv4 representation as ipv6 address. */
184 memset(address, 0, 16);
185 memcpy(&address[12], &ban->address, 4);
186 memset(&address[10], 0xff, 2); /* IPv4 */
187 Msg_banList_addEntry(msg, i++, address, ban->mask, ban->name,
188 hexhash, ban->reason, timestr, ban->duration);
193 void Ban_clearBanList(void)
196 struct dlist *itr, *save;
197 list_iterate_safe(itr, save, &banlist) {
198 ban = list_get_entry(itr, ban_t, node);
201 list_del(&ban->node);
207 void Ban_putBanList(message_t *msg, int n_bans)
212 char *hexhash, *name, *reason, *start;
213 uint32_t duration, mask;
216 for (i = 0; i < n_bans; i++) {
217 Msg_banList_getEntry(msg, i, &address, &mask, &name, &hexhash, &reason, &start, &duration);
218 ban = malloc(sizeof(ban_t));
220 Log_fatal("Out of memory");
221 memset(ban, 0, sizeof(ban_t));
222 SSLi_hex2hash(hexhash, ban->hash);
223 memcpy(&ban->address, &address[12], 4);
225 ban->reason = strdup(reason);
226 ban->name = strdup(name);
227 strptime(start, "%Y-%m-%dT%H:%M:%S", ×pec);
228 ban->time = mktime(×pec);
229 ban->startTime = ban->time * 1000000LL;
230 ban->duration = duration;
231 list_add_tail(&ban->node, &banlist);
234 banlist_changed = true;
235 if(getBoolConf(SYNC_BANFILE))
239 static void Ban_saveBanFile(void)
246 if (!banlist_changed)
248 file = fopen(getStrConf(BANFILE), "w");
250 Log_warn("Could not save banlist to file %s: %s", getStrConf(BANFILE), strerror(errno));
253 list_iterate(itr, &banlist) {
254 ban = list_get_entry(itr, ban_t, node);
255 SSLi_hash2hex(ban->hash, hexhash);
256 fprintf(file, "%s,%s,%d,%ld,%d,%s,%s\n", hexhash, inet_ntoa(*((struct in_addr *)&ban->address)),
257 ban->mask, (long int)ban->time, ban->duration, ban->name, ban->reason);
260 banlist_changed = false;
261 Log_info("Banlist file '%s': %d entries written", getStrConf(BANFILE), bancount);
264 static void Ban_readBanFile(void)
268 char line[1024], *hexhash, *address, *name, *reason;
269 uint32_t mask, duration;
274 file = fopen(getStrConf(BANFILE), "r");
276 Log_warn("Could not read banlist file %s: %s", getStrConf(BANFILE), strerror(errno));
279 while (fgets(line, 1024, file) != NULL) {
280 p = strtok(line, ",");
282 p = strtok(NULL, ",");
283 if (p == NULL) break;
285 p = strtok(NULL, ",");
286 if (p == NULL) break;
287 mask = strtoul(p, NULL, 0);
288 p = strtok(NULL, ",");
289 if (p == NULL) break;
290 time = strtoul(p, NULL, 0);
291 p = strtok(NULL, ",");
292 if (p == NULL) break;
293 duration = strtoul(p, NULL, 0);
294 p = strtok(NULL, ",");
295 if (p == NULL) break;
297 p = strtok(NULL, "\n");
298 if (p == NULL) break;
301 ban = malloc(sizeof(ban_t));
303 Log_fatal("Out of memory");
304 memset(ban, 0, sizeof(ban_t));
305 SSLi_hex2hash(hexhash, ban->hash);
306 inet_aton(address, (struct in_addr *)&ban->address);
307 ban->name = strdup(name);
308 ban->reason = strdup(reason);
309 if (ban->name == NULL || ban->reason == NULL)
310 Log_fatal("Out of memory");
312 ban->duration = duration;
314 ban->startTime = ban->time * 1000000LL;
315 list_add_tail(&ban->node, &banlist);
317 Log_debug("Banfile: H = '%s' A = '%s' M = %d U = '%s' R = '%s'", hexhash, address, ban->mask, ban->name, ban->reason);
320 Log_info("Banlist file '%s': %d entries read", getStrConf(BANFILE), bancount);