1 /* Copyright (C) 2009-2012, Martin Johansson <martin@fatbob.nu>
2 Copyright (C) 2005-2012, 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->name, ban->reason, hexhash, inet_ntoa(*((struct in_addr *)&ban->address)),
97 void Ban_pruneBanned()
102 uint64_t bantime_long;
104 list_iterate(itr, &banlist) {
105 ban = list_get_entry(itr, ban_t, node);
106 bantime_long = ban->duration * 1000000LL;
108 SSLi_hash2hex(ban->hash, hexhash);
109 Log_debug("BL: User %s Reason: '%s' Hash: %s IP: %s Time left: %d",
110 ban->name, ban->reason, hexhash, inet_ntoa(*((struct in_addr *)&ban->address)),
111 bantime_long / 1000000LL - Timer_elapsed(&ban->startTime) / 1000000LL);
113 /* Duration of 0 = forever */
114 if (ban->duration != 0 && Timer_isElapsed(&ban->startTime, bantime_long)) {
117 list_del(&ban->node);
120 banlist_changed = true;
121 if(getBoolConf(SYNC_BANFILE))
127 bool_t Ban_isBanned(client_t *client)
131 list_iterate(itr, &banlist) {
132 ban = list_get_entry(itr, ban_t, node);
133 if (memcmp(ban->hash, client->hash, 20) == 0)
140 bool_t Ban_isBannedAddr(in_addr_t *addr)
145 in_addr_t tempaddr1, tempaddr2;
147 list_iterate(itr, &banlist) {
148 ban = list_get_entry(itr, ban_t, node);
149 mask = ban->mask - 96;
150 if (mask < 32) { /* XXX - only ipv4 support */
151 memcpy(&tempaddr1, addr, sizeof(in_addr_t));
152 memcpy(&tempaddr2, &ban->address, sizeof(in_addr_t));
153 tempaddr1 &= (2 ^ mask) - 1;
154 tempaddr2 &= (2 ^ mask) - 1;
156 if (memcmp(&tempaddr1, &tempaddr2, sizeof(in_addr_t)) == 0)
162 int Ban_getBanCount(void)
167 message_t *Ban_getBanList(void)
178 msg = Msg_banList_create(bancount);
179 list_iterate(itr, &banlist) {
180 ban = list_get_entry(itr, ban_t, node);
181 gmtime_r(&ban->time, ×pec);
182 strftime(timestr, 32, "%Y-%m-%dT%H:%M:%S", ×pec);
183 SSLi_hash2hex(ban->hash, hexhash);
184 /* ipv4 representation as ipv6 address. */
185 memset(address, 0, 16);
186 memcpy(&address[12], &ban->address, 4);
187 memset(&address[10], 0xff, 2); /* IPv4 */
188 Msg_banList_addEntry(msg, i++, address, ban->mask, ban->name,
189 hexhash, ban->reason, timestr, ban->duration);
194 void Ban_clearBanList(void)
197 struct dlist *itr, *save;
198 list_iterate_safe(itr, save, &banlist) {
199 ban = list_get_entry(itr, ban_t, node);
202 list_del(&ban->node);
208 void Ban_putBanList(message_t *msg, int n_bans)
213 char *hexhash, *name, *reason, *start;
214 uint32_t duration, mask;
217 for (i = 0; i < n_bans; i++) {
218 Msg_banList_getEntry(msg, i, &address, &mask, &name, &hexhash, &reason, &start, &duration);
219 ban = malloc(sizeof(ban_t));
221 Log_fatal("Out of memory");
222 memset(ban, 0, sizeof(ban_t));
223 SSLi_hex2hash(hexhash, ban->hash);
224 memcpy(&ban->address, &address[12], 4);
226 ban->reason = strdup(reason);
227 ban->name = strdup(name);
228 strptime(start, "%Y-%m-%dT%H:%M:%S", ×pec);
229 ban->time = mktime(×pec);
230 Timer_init(&ban->startTime);
231 ban->duration = duration;
232 list_add_tail(&ban->node, &banlist);
235 banlist_changed = true;
236 if(getBoolConf(SYNC_BANFILE))
240 static void Ban_saveBanFile(void)
247 if (!banlist_changed)
249 file = fopen(getStrConf(BANFILE), "w");
251 Log_warn("Could not save banlist to file %s: %s", getStrConf(BANFILE), strerror(errno));
254 list_iterate(itr, &banlist) {
255 ban = list_get_entry(itr, ban_t, node);
256 SSLi_hash2hex(ban->hash, hexhash);
257 fprintf(file, "%s,%s,%d,%d,%d,%s,%s\n", hexhash, inet_ntoa(*((struct in_addr *)&ban->address)),
258 ban->mask, ban->time, ban->duration, ban->name, ban->reason);
263 static void Ban_readBanFile(void)
267 char line[512], *hexhash, *address, *name, *reason;
268 uint32_t mask, duration;
273 file = fopen(getStrConf(BANFILE), "r");
275 Log_warn("Could not read banlist file %s: %s", getStrConf(BANFILE), strerror(errno));
278 while (fgets(line, 512, file) != NULL) {
279 p = strtok(line, ",");
281 p = strtok(NULL, ",");
282 if (p == NULL) break;
284 p = strtok(NULL, ",");
285 if (p == NULL) break;
286 mask = strtoul(p, NULL, 0);
287 p = strtok(NULL, ",");
288 if (p == NULL) break;
289 time = strtoul(p, NULL, 0);
290 p = strtok(NULL, ",");
291 if (p == NULL) break;
292 duration = strtoul(p, NULL, 0);
293 p = strtok(NULL, ",");
294 if (p == NULL) break;
296 p = strtok(NULL, "\n");
297 if (p == NULL) break;
300 ban = malloc(sizeof(ban_t));
302 Log_fatal("Out of memory");
303 memset(ban, 0, sizeof(ban_t));
304 SSLi_hex2hash(hexhash, ban->hash);
305 inet_aton(address, (struct in_addr *)&ban->address);
306 ban->name = strdup(name);
307 ban->reason = strdup(reason);
309 ban->duration = duration;
311 Timer_init(&ban->startTime);
312 list_add_tail(&ban->node, &banlist);
314 Log_debug("Banfile: H = '%s' A = '%s' M = %d U = '%s' R = '%s'", hexhash, address, ban->mask, ban->name, ban->reason);