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.
41 static void Ban_saveBanFile(void);
42 static void Ban_readBanFile(void);
45 declare_list(banlist);
46 static int bancount; /* = 0 */
47 static int ban_duration;
48 static bool_t banlist_changed;
52 ban_duration = getIntConf(BAN_LENGTH);
53 /* Read ban file here */
54 if (getStrConf(BANFILE) != NULL)
61 if (getStrConf(BANFILE) != NULL)
67 void Ban_UserBan(client_t *client, char *reason)
72 ban = malloc(sizeof(ban_t));
74 Log_fatal("Out of memory");
75 memset(ban, 0, sizeof(ban_t));
77 memcpy(ban->hash, client->hash, 20);
78 if (client->remote_tcp.ss_family == AF_INET) {
79 memcpy(&ban->address, &(((struct sockaddr_in*)&client->remote_tcp)->sin_addr), sizeof(in_addr_t));
80 ban->mask = sizeof(in_addr_t);
82 memcpy(&ban->address, &(((struct sockaddr_in6*)&client->remote_tcp)->sin6_addr), 4 * sizeof(in_addr_t));
83 ban->mask = 4 * sizeof(in_addr_t);
85 ban->reason = strdup(reason);
86 ban->name = strdup(client->username);
87 ban->time = time(NULL);
88 ban->duration = ban_duration;
89 Timer_init(&ban->startTime);
90 list_add_tail(&ban->node, &banlist);
92 banlist_changed = true;
93 if(getBoolConf(SYNC_BANFILE))
96 SSLi_hash2hex(ban->hash, hexhash);
98 Log_info_client(client, "User kickbanned. Reason: '%s' Hash: %s IP: %s Banned for: %d seconds",
99 ban->reason, hexhash, Util_clientAddressToString(client), ban->duration);
103 void Ban_pruneBanned()
108 uint64_t bantime_long;
110 list_iterate(itr, &banlist) {
111 ban = list_get_entry(itr, ban_t, node);
112 bantime_long = ban->duration * 1000000LL;
114 SSLi_hash2hex(ban->hash, hexhash);
115 Log_debug("BL: User %s Reason: '%s' Hash: %s IP: %s Time left: %d",
116 ban->name, ban->reason, hexhash, inet_ntoa(*((struct in_addr *)&ban->address)),
117 bantime_long / 1000000LL - Timer_elapsed(&ban->startTime) / 1000000LL);
119 /* Duration of 0 = forever */
120 if (ban->duration != 0 && Timer_isElapsed(&ban->startTime, bantime_long)) {
123 list_del(&ban->node);
126 banlist_changed = true;
127 if(getBoolConf(SYNC_BANFILE))
133 bool_t Ban_isBanned(client_t *client)
137 list_iterate(itr, &banlist) {
138 ban = list_get_entry(itr, ban_t, node);
139 if (memcmp(ban->hash, client->hash, 20) == 0)
146 bool_t Ban_isBannedAddr(struct sockaddr_storage *address)
150 in_addr_t tempaddr1, tempaddr2;
152 list_iterate(itr, &banlist) {
153 ban = list_get_entry(itr, ban_t, node);
155 if(ban->mask == sizeof(in_addr_t)) {
156 if(memcmp(ban->address, &((struct sockaddr_in *)address)->sin_addr, ban->mask) == 0)
160 if(memcmp(ban->address, &((struct sockaddr_in6 *)address)->sin6_addr, ban->mask) == 0)
167 int Ban_getBanCount(void)
172 message_t *Ban_getBanList(void)
183 msg = Msg_banList_create(bancount);
184 list_iterate(itr, &banlist) {
185 ban = list_get_entry(itr, ban_t, node);
186 gmtime_r(&ban->time, ×pec);
187 strftime(timestr, 32, "%Y-%m-%dT%H:%M:%S", ×pec);
188 SSLi_hash2hex(ban->hash, hexhash);
189 /* ipv4 representation as ipv6 address. */
190 memset(address, 0, 16);
191 memcpy(&address[12], &ban->address, 4);
192 memset(&address[10], 0xff, 2); /* IPv4 */
193 Msg_banList_addEntry(msg, i++, address, ban->mask, ban->name,
194 hexhash, ban->reason, timestr, ban->duration);
199 void Ban_clearBanList(void)
202 struct dlist *itr, *save;
203 list_iterate_safe(itr, save, &banlist) {
204 ban = list_get_entry(itr, ban_t, node);
207 list_del(&ban->node);
213 void Ban_putBanList(message_t *msg, int n_bans)
218 char *hexhash, *name, *reason, *start;
219 uint32_t duration, mask;
222 for (i = 0; i < n_bans; i++) {
223 Msg_banList_getEntry(msg, i, &address, &mask, &name, &hexhash, &reason, &start, &duration);
224 ban = malloc(sizeof(ban_t));
226 Log_fatal("Out of memory");
227 memset(ban, 0, sizeof(ban_t));
228 SSLi_hex2hash(hexhash, ban->hash);
229 memcpy(&ban->address, &address[12], 4);
231 ban->reason = strdup(reason);
232 ban->name = strdup(name);
233 strptime(start, "%Y-%m-%dT%H:%M:%S", ×pec);
234 ban->time = mktime(×pec);
235 ban->startTime = ban->time * 1000000LL;
236 ban->duration = duration;
237 list_add_tail(&ban->node, &banlist);
240 banlist_changed = true;
241 if(getBoolConf(SYNC_BANFILE))
245 static void Ban_saveBanFile(void)
252 if (!banlist_changed)
254 file = fopen(getStrConf(BANFILE), "w");
256 Log_warn("Could not save banlist to file %s: %s", getStrConf(BANFILE), strerror(errno));
259 list_iterate(itr, &banlist) {
260 ban = list_get_entry(itr, ban_t, node);
261 SSLi_hash2hex(ban->hash, hexhash);
262 fprintf(file, "%s,%s,%d,%ld,%d,%s,%s\n", hexhash, inet_ntoa(*((struct in_addr *)&ban->address)),
263 ban->mask, (long int)ban->time, ban->duration, ban->name, ban->reason);
266 banlist_changed = false;
267 Log_info("Banlist file '%s': %d entries written", getStrConf(BANFILE), bancount);
270 static void Ban_readBanFile(void)
274 char line[1024], *hexhash, *address, *name, *reason;
275 uint32_t mask, duration;
280 file = fopen(getStrConf(BANFILE), "r");
282 Log_warn("Could not read banlist file %s: %s", getStrConf(BANFILE), strerror(errno));
285 while (fgets(line, 1024, file) != NULL) {
286 p = strtok(line, ",");
288 p = strtok(NULL, ",");
289 if (p == NULL) break;
291 p = strtok(NULL, ",");
292 if (p == NULL) break;
293 mask = strtoul(p, NULL, 0);
294 p = strtok(NULL, ",");
295 if (p == NULL) break;
296 time = strtoul(p, NULL, 0);
297 p = strtok(NULL, ",");
298 if (p == NULL) break;
299 duration = strtoul(p, NULL, 0);
300 p = strtok(NULL, ",");
301 if (p == NULL) break;
303 p = strtok(NULL, "\n");
304 if (p == NULL) break;
307 ban = malloc(sizeof(ban_t));
309 Log_fatal("Out of memory");
310 memset(ban, 0, sizeof(ban_t));
311 SSLi_hex2hash(hexhash, ban->hash);
312 inet_aton(address, (struct in_addr *)&ban->address);
313 ban->name = strdup(name);
314 ban->reason = strdup(reason);
315 if (ban->name == NULL || ban->reason == NULL)
316 Log_fatal("Out of memory");
318 ban->duration = duration;
320 ban->startTime = ban->time * 1000000LL;
321 list_add_tail(&ban->node, &banlist);
323 Log_debug("Banfile: H = '%s' A = '%s' M = %d U = '%s' R = '%s'", hexhash, address, ban->mask, ban->name, ban->reason);
326 Log_info("Banlist file '%s': %d entries read", getStrConf(BANFILE), bancount);