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 Log_info_client(client, "User kickbanned. Reason: '%s' Hash: %s IP: %s Banned for: %d seconds",
98 ban->reason, hexhash, client->addressString, ban->duration);
102 void Ban_pruneBanned()
107 uint64_t bantime_long;
109 list_iterate(itr, &banlist) {
110 ban = list_get_entry(itr, ban_t, node);
111 bantime_long = ban->duration * 1000000LL;
113 SSLi_hash2hex(ban->hash, hexhash);
114 Log_debug("BL: User %s Reason: '%s' Hash: %s IP: %s Time left: %d",
115 ban->name, ban->reason, hexhash, inet_ntoa(*((struct in_addr *)&ban->address)),
116 bantime_long / 1000000LL - Timer_elapsed(&ban->startTime) / 1000000LL);
118 /* Duration of 0 = forever */
119 if (ban->duration != 0 && Timer_isElapsed(&ban->startTime, bantime_long)) {
122 list_del(&ban->node);
125 banlist_changed = true;
126 if(getBoolConf(SYNC_BANFILE))
132 bool_t Ban_isBanned(client_t *client)
136 list_iterate(itr, &banlist) {
137 ban = list_get_entry(itr, ban_t, node);
138 if (memcmp(ban->hash, client->hash, 20) == 0)
145 bool_t Ban_isBannedAddr(struct sockaddr_storage *address)
149 in_addr_t tempaddr1, tempaddr2;
151 list_iterate(itr, &banlist) {
152 ban = list_get_entry(itr, ban_t, node);
154 if(ban->mask == sizeof(in_addr_t)) {
155 if(memcmp(ban->address, &((struct sockaddr_in *)address)->sin_addr, ban->mask) == 0)
159 if(memcmp(ban->address, &((struct sockaddr_in6 *)address)->sin6_addr, ban->mask) == 0)
166 int Ban_getBanCount(void)
171 message_t *Ban_getBanList(void)
182 msg = Msg_banList_create(bancount);
183 list_iterate(itr, &banlist) {
184 ban = list_get_entry(itr, ban_t, node);
185 gmtime_r(&ban->time, ×pec);
186 strftime(timestr, 32, "%Y-%m-%dT%H:%M:%S", ×pec);
187 SSLi_hash2hex(ban->hash, hexhash);
188 /* ipv4 representation as ipv6 address. */
189 memset(address, 0, 16);
190 memcpy(&address[12], &ban->address, 4);
191 memset(&address[10], 0xff, 2); /* IPv4 */
192 Msg_banList_addEntry(msg, i++, address, ban->mask, ban->name,
193 hexhash, ban->reason, timestr, ban->duration);
198 void Ban_clearBanList(void)
201 struct dlist *itr, *save;
202 list_iterate_safe(itr, save, &banlist) {
203 ban = list_get_entry(itr, ban_t, node);
206 list_del(&ban->node);
212 void Ban_putBanList(message_t *msg, int n_bans)
217 char *hexhash, *name, *reason, *start;
218 uint32_t duration, mask;
221 for (i = 0; i < n_bans; i++) {
222 Msg_banList_getEntry(msg, i, &address, &mask, &name, &hexhash, &reason, &start, &duration);
223 ban = malloc(sizeof(ban_t));
225 Log_fatal("Out of memory");
226 memset(ban, 0, sizeof(ban_t));
227 SSLi_hex2hash(hexhash, ban->hash);
228 memcpy(&ban->address, &address[12], 4);
230 ban->reason = strdup(reason);
231 ban->name = strdup(name);
232 strptime(start, "%Y-%m-%dT%H:%M:%S", ×pec);
233 ban->time = mktime(×pec);
234 ban->startTime = ban->time * 1000000LL;
235 ban->duration = duration;
236 list_add_tail(&ban->node, &banlist);
239 banlist_changed = true;
240 if(getBoolConf(SYNC_BANFILE))
244 static void Ban_saveBanFile(void)
251 if (!banlist_changed)
253 file = fopen(getStrConf(BANFILE), "w");
255 Log_warn("Could not save banlist to file %s: %s", getStrConf(BANFILE), strerror(errno));
258 list_iterate(itr, &banlist) {
259 ban = list_get_entry(itr, ban_t, node);
260 SSLi_hash2hex(ban->hash, hexhash);
261 fprintf(file, "%s,%s,%d,%ld,%d,%s,%s\n", hexhash, inet_ntoa(*((struct in_addr *)&ban->address)),
262 ban->mask, (long int)ban->time, ban->duration, ban->name, ban->reason);
265 banlist_changed = false;
266 Log_info("Banlist file '%s': %d entries written", getStrConf(BANFILE), bancount);
269 static void Ban_readBanFile(void)
273 char line[1024], *hexhash, *address, *name, *reason;
274 uint32_t mask, duration;
279 file = fopen(getStrConf(BANFILE), "r");
281 Log_warn("Could not read banlist file %s: %s", getStrConf(BANFILE), strerror(errno));
284 while (fgets(line, 1024, file) != NULL) {
285 p = strtok(line, ",");
287 p = strtok(NULL, ",");
288 if (p == NULL) break;
290 p = strtok(NULL, ",");
291 if (p == NULL) break;
292 mask = strtoul(p, NULL, 0);
293 p = strtok(NULL, ",");
294 if (p == NULL) break;
295 time = strtoul(p, NULL, 0);
296 p = strtok(NULL, ",");
297 if (p == NULL) break;
298 duration = strtoul(p, NULL, 0);
299 p = strtok(NULL, ",");
300 if (p == NULL) break;
302 p = strtok(NULL, "\n");
303 if (p == NULL) break;
306 ban = malloc(sizeof(ban_t));
308 Log_fatal("Out of memory");
309 memset(ban, 0, sizeof(ban_t));
310 SSLi_hex2hash(hexhash, ban->hash);
311 inet_aton(address, (struct in_addr *)&ban->address);
312 ban->name = strdup(name);
313 ban->reason = strdup(reason);
314 if (ban->name == NULL || ban->reason == NULL)
315 Log_fatal("Out of memory");
317 ban->duration = duration;
319 ban->startTime = ban->time * 1000000LL;
320 list_add_tail(&ban->node, &banlist);
322 Log_debug("Banfile: H = '%s' A = '%s' M = %d U = '%s' R = '%s'", hexhash, address, ban->mask, ban->name, ban->reason);
325 Log_info("Banlist file '%s': %d entries read", getStrConf(BANFILE), bancount);