X-Git-Url: http://git.code-monkey.de/?a=blobdiff_plain;f=src%2Fban.c;h=229b0de1fd637232322e5a7c9dec8885a2d2b63c;hb=f437c88e9885c332a11fce2babc53c22dfd6e86e;hp=710148508e2be5bb4f49a1bf9799dc53ef50db42;hpb=6ef74bad35256fee51eea502bf040696848ee81f;p=umurmur.git diff --git a/src/ban.c b/src/ban.c index 7101485..229b0de 100644 --- a/src/ban.c +++ b/src/ban.c @@ -1,5 +1,5 @@ -/* Copyright (C) 2009-2012, Martin Johansson - Copyright (C) 2005-2012, Thorvald Natvig +/* Copyright (C) 2009-2014, Martin Johansson + Copyright (C) 2005-2014, Thorvald Natvig All rights reserved. @@ -37,20 +37,32 @@ #include "conf.h" #include "ssl.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) { ban_t *ban; @@ -60,10 +72,15 @@ void Ban_UserBan(client_t *client, char *reason) 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)); - ban->mask = 128; + 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); @@ -71,11 +88,14 @@ void Ban_UserBan(client_t *client, char *reason) 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_client(client, "User kickbanned. Reason: '%s' Hash: %s IP: %s Banned for: %d seconds", - ban->name, ban->reason, hexhash, inet_ntoa(*((struct in_addr *)&ban->address)), - ban->duration); + ban->reason, hexhash, client->addressString, ban->duration); } @@ -85,15 +105,15 @@ void Ban_pruneBanned() ban_t *ban; char hexhash[41]; 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_long / 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 /* Duration of 0 = forever */ if (ban->duration != 0 && Timer_isElapsed(&ban->startTime, bantime_long)) { @@ -102,6 +122,9 @@ void Ban_pruneBanned() list_del(&ban->node); free(ban); bancount--; + banlist_changed = true; + if(getBoolConf(SYNC_BANFILE)) + Ban_saveBanFile(); } } } @@ -112,31 +135,30 @@ 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; - int mask; in_addr_t tempaddr1, tempaddr2; - + list_iterate(itr, &banlist) { ban = list_get_entry(itr, ban_t, node); - mask = ban->mask - 96; - if (mask < 32) { /* XXX - only ipv4 support */ - memcpy(&tempaddr1, addr, sizeof(in_addr_t)); - memcpy(&tempaddr2, &ban->address, sizeof(in_addr_t)); - tempaddr1 &= (2 ^ mask) - 1; - tempaddr2 &= (2 ^ mask) - 1; + + 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; } - if (memcmp(&tempaddr1, &tempaddr2, sizeof(in_addr_t)) == 0) - return true; } return false; } @@ -156,7 +178,7 @@ message_t *Ban_getBanList(void) 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); @@ -168,12 +190,12 @@ message_t *Ban_getBanList(void) 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); + hexhash, ban->reason, timestr, ban->duration); } return msg; } -void Ban_clearBanList() +void Ban_clearBanList(void) { ban_t *ban; struct dlist *itr, *save; @@ -195,7 +217,7 @@ void Ban_putBanList(message_t *msg, int n_bans) 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)); @@ -209,9 +231,96 @@ void Ban_putBanList(message_t *msg, int n_bans) ban->name = strdup(name); strptime(start, "%Y-%m-%dT%H:%M:%S", ×pec); ban->time = mktime(×pec); - Timer_init(&ban->startTime); + 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); }