X-Git-Url: http://git.code-monkey.de/?a=blobdiff_plain;f=src%2Fban.c;h=3c7c4ffa656ea26c2ab285192b03f9466d4f08d5;hb=bb5f5ae82bdcb7b5189032940d0b609dc12be70b;hp=29ad8a3639e58a2f39772a3a1c549bb93017888a;hpb=5b8dc3fd052b892f75f167af91193e88e321f42c;p=umurmur.git diff --git a/src/ban.c b/src/ban.c index 29ad8a3..3c7c4ff 100644 --- a/src/ban.c +++ b/src/ban.c @@ -1,5 +1,5 @@ -/* Copyright (C) 2009-2011, Martin Johansson - Copyright (C) 2005-2011, Thorvald Natvig +/* Copyright (C) 2009-2014, Martin Johansson + Copyright (C) 2005-2014, Thorvald Natvig All rights reserved. @@ -30,14 +30,39 @@ */ #include +#include #include "log.h" #include "list.h" #include "ban.h" #include "conf.h" #include "ssl.h" +#include "util.h" + +static void Ban_saveBanFile(void); +static void Ban_readBanFile(void); + declare_list(banlist); static int bancount; /* = 0 */ +static int ban_duration; +static bool_t banlist_changed; + +void Ban_init(void) +{ + ban_duration = getIntConf(BAN_LENGTH); + /* Read ban file here */ + if (getStrConf(BANFILE) != NULL) + Ban_readBanFile(); +} + +void Ban_deinit(void) +{ + /* Save banlist */ + if (getStrConf(BANFILE) != NULL) + Ban_saveBanFile(); + + Ban_clearBanList(); +} void Ban_UserBan(client_t *client, char *reason) { @@ -45,44 +70,62 @@ void Ban_UserBan(client_t *client, char *reason) char hexhash[41]; ban = malloc(sizeof(ban_t)); + if (ban == NULL) + Log_fatal("Out of memory"); + memset(ban, 0, sizeof(ban_t)); + memcpy(ban->hash, client->hash, 20); - memcpy(&ban->address, &client->remote_tcp.sin_addr, sizeof(in_addr_t)); + if (client->remote_tcp.ss_family == AF_INET) { + memcpy(&ban->address, &(((struct sockaddr_in*)&client->remote_tcp)->sin_addr), sizeof(in_addr_t)); + ban->mask = sizeof(in_addr_t); + } else { + memcpy(&ban->address, &(((struct sockaddr_in6*)&client->remote_tcp)->sin6_addr), 4 * sizeof(in_addr_t)); + ban->mask = 4 * sizeof(in_addr_t); + } ban->reason = strdup(reason); ban->name = strdup(client->username); + ban->time = time(NULL); + ban->duration = ban_duration; Timer_init(&ban->startTime); list_add_tail(&ban->node, &banlist); - + bancount++; + banlist_changed = true; + if(getBoolConf(SYNC_BANFILE)) + Ban_saveBanFile(); + SSLi_hash2hex(ban->hash, hexhash); - Log_info("User %s kickbanned. Reason: '%s' Hash: %s IP: %s Banned for: %d seconds", - ban->name, ban->reason, hexhash, inet_ntoa(*((struct in_addr *)&ban->address)), - getIntConf(BAN_LENGTH)); + + Log_info_client(client, "User kickbanned. Reason: '%s' Hash: %s IP: %s Banned for: %d seconds", + ban->reason, hexhash, Util_clientAddressToString(client), ban->duration); } void Ban_pruneBanned() { struct dlist *itr; - static int64_t bantime = 0; ban_t *ban; char hexhash[41]; - - if (bantime == 0) { - bantime = getIntConf(BAN_LENGTH) * 1000000LL; - } - + uint64_t bantime_long; + list_iterate(itr, &banlist) { ban = list_get_entry(itr, ban_t, node); + bantime_long = ban->duration * 1000000LL; #ifdef DEBUG SSLi_hash2hex(ban->hash, hexhash); Log_debug("BL: User %s Reason: '%s' Hash: %s IP: %s Time left: %d", - ban->name, ban->reason, hexhash, inet_ntoa(*((struct in_addr *)&ban->address)), - bantime / 1000000LL - Timer_elapsed(&ban->startTime) / 1000000LL); + ban->name, ban->reason, hexhash, inet_ntoa(*((struct in_addr *)&ban->address)), + bantime_long / 1000000LL - Timer_elapsed(&ban->startTime) / 1000000LL); #endif - if (Timer_isElapsed(&ban->startTime, bantime)) { + /* Duration of 0 = forever */ + if (ban->duration != 0 && Timer_isElapsed(&ban->startTime, bantime_long)) { free(ban->name); free(ban->reason); list_del(&ban->node); free(ban); + bancount--; + banlist_changed = true; + if(getBoolConf(SYNC_BANFILE)) + Ban_saveBanFile(); } } } @@ -93,22 +136,192 @@ bool_t Ban_isBanned(client_t *client) ban_t *ban; list_iterate(itr, &banlist) { ban = list_get_entry(itr, ban_t, node); - if (memcmp(ban->hash, client->hash, 20) == 0) + if (memcmp(ban->hash, client->hash, 20) == 0) return true; } return false; - + } -bool_t Ban_isBannedAddr(in_addr_t *addr) +bool_t Ban_isBannedAddr(struct sockaddr_storage *address) { struct dlist *itr; ban_t *ban; + in_addr_t tempaddr1, tempaddr2; + list_iterate(itr, &banlist) { ban = list_get_entry(itr, ban_t, node); - if (memcmp(&ban->address, addr, sizeof(in_addr_t)) == 0) - return true; + + if(ban->mask == sizeof(in_addr_t)) { + if(memcmp(ban->address, &((struct sockaddr_in *)address)->sin_addr, ban->mask) == 0) + return true; + } + else { + if(memcmp(ban->address, &((struct sockaddr_in6 *)address)->sin6_addr, ban->mask) == 0) + return true; + } } return false; } +int Ban_getBanCount(void) +{ + return bancount; +} + +message_t *Ban_getBanList(void) +{ + int i = 0; + struct dlist *itr; + ban_t *ban; + message_t *msg; + struct tm timespec; + char timestr[32]; + char hexhash[41]; + uint8_t address[16]; + + msg = Msg_banList_create(bancount); + list_iterate(itr, &banlist) { + ban = list_get_entry(itr, ban_t, node); + gmtime_r(&ban->time, ×pec); + strftime(timestr, 32, "%Y-%m-%dT%H:%M:%S", ×pec); + SSLi_hash2hex(ban->hash, hexhash); + /* ipv4 representation as ipv6 address. */ + memset(address, 0, 16); + memcpy(&address[12], &ban->address, 4); + memset(&address[10], 0xff, 2); /* IPv4 */ + Msg_banList_addEntry(msg, i++, address, ban->mask, ban->name, + hexhash, ban->reason, timestr, ban->duration); + } + return msg; +} + +void Ban_clearBanList(void) +{ + ban_t *ban; + struct dlist *itr, *save; + list_iterate_safe(itr, save, &banlist) { + ban = list_get_entry(itr, ban_t, node); + free(ban->name); + free(ban->reason); + list_del(&ban->node); + free(ban); + bancount--; + } +} + +void Ban_putBanList(message_t *msg, int n_bans) +{ + int i = 0; + struct tm timespec; + ban_t *ban; + char *hexhash, *name, *reason, *start; + uint32_t duration, mask; + uint8_t *address; + + for (i = 0; i < n_bans; i++) { + Msg_banList_getEntry(msg, i, &address, &mask, &name, &hexhash, &reason, &start, &duration); + ban = malloc(sizeof(ban_t)); + if (ban == NULL) + Log_fatal("Out of memory"); + memset(ban, 0, sizeof(ban_t)); + SSLi_hex2hash(hexhash, ban->hash); + memcpy(&ban->address, &address[12], 4); + ban->mask = mask; + ban->reason = strdup(reason); + ban->name = strdup(name); + strptime(start, "%Y-%m-%dT%H:%M:%S", ×pec); + ban->time = mktime(×pec); + ban->startTime = ban->time * 1000000LL; + ban->duration = duration; + list_add_tail(&ban->node, &banlist); + bancount++; + } + banlist_changed = true; + if(getBoolConf(SYNC_BANFILE)) + Ban_saveBanFile(); +} + +static void Ban_saveBanFile(void) +{ + struct dlist *itr; + ban_t *ban; + char hexhash[41]; + FILE *file; + + if (!banlist_changed) + return; + file = fopen(getStrConf(BANFILE), "w"); + if (file == NULL) { + Log_warn("Could not save banlist to file %s: %s", getStrConf(BANFILE), strerror(errno)); + return; + } + list_iterate(itr, &banlist) { + ban = list_get_entry(itr, ban_t, node); + SSLi_hash2hex(ban->hash, hexhash); + fprintf(file, "%s,%s,%d,%ld,%d,%s,%s\n", hexhash, inet_ntoa(*((struct in_addr *)&ban->address)), + ban->mask, (long int)ban->time, ban->duration, ban->name, ban->reason); + } + fclose(file); + banlist_changed = false; + Log_info("Banlist file '%s': %d entries written", getStrConf(BANFILE), bancount); +} + +static void Ban_readBanFile(void) +{ + struct dlist *itr; + ban_t *ban; + char line[1024], *hexhash, *address, *name, *reason; + uint32_t mask, duration; + time_t time; + char *p; + FILE *file; + + file = fopen(getStrConf(BANFILE), "r"); + if (file == NULL) { + Log_warn("Could not read banlist file %s: %s", getStrConf(BANFILE), strerror(errno)); + return; + } + while (fgets(line, 1024, file) != NULL) { + p = strtok(line, ","); + hexhash = p; + p = strtok(NULL, ","); + if (p == NULL) break; + address = p; + p = strtok(NULL, ","); + if (p == NULL) break; + mask = strtoul(p, NULL, 0); + p = strtok(NULL, ","); + if (p == NULL) break; + time = strtoul(p, NULL, 0); + p = strtok(NULL, ","); + if (p == NULL) break; + duration = strtoul(p, NULL, 0); + p = strtok(NULL, ","); + if (p == NULL) break; + name = p; + p = strtok(NULL, "\n"); + if (p == NULL) break; + reason = p; + + ban = malloc(sizeof(ban_t)); + if (ban == NULL) + Log_fatal("Out of memory"); + memset(ban, 0, sizeof(ban_t)); + SSLi_hex2hash(hexhash, ban->hash); + inet_aton(address, (struct in_addr *)&ban->address); + ban->name = strdup(name); + ban->reason = strdup(reason); + if (ban->name == NULL || ban->reason == NULL) + Log_fatal("Out of memory"); + ban->time = time; + ban->duration = duration; + ban->mask = mask; + ban->startTime = ban->time * 1000000LL; + list_add_tail(&ban->node, &banlist); + bancount++; + Log_debug("Banfile: H = '%s' A = '%s' M = %d U = '%s' R = '%s'", hexhash, address, ban->mask, ban->name, ban->reason); + } + fclose(file); + Log_info("Banlist file '%s': %d entries read", getStrConf(BANFILE), bancount); +}