Browse Source

ckdb - handle events vs ovents

master
kanoi 9 years ago
parent
commit
ddeed87874
  1. 41
      src/ckdb.c
  2. 36
      src/ckdb.h
  3. 50
      src/ckdb_cmd.c
  4. 190
      src/ckdb_data.c
  5. 60
      src/ckdb_dbio.c

41
src/ckdb.c

@ -1248,7 +1248,13 @@ static void alloc_storage()
ips_free = k_new_list("IPs", sizeof(IPS), ALLOC_IPS, LIMIT_IPS, true); ips_free = k_new_list("IPs", sizeof(IPS), ALLOC_IPS, LIMIT_IPS, true);
ips_store = k_new_store(ips_free); ips_store = k_new_store(ips_free);
ips_root = new_ktree(NULL, cmp_ips, ips_free); ips_root = new_ktree(NULL, cmp_ips, ips_free);
ips_add(IPS_GROUP_OK, "127.0.0.1", "local", false, true, 0, false); // Always default to allow localhost
K_WLOCK(ips_free);
ips_add(IPS_GROUP_OK, "127.0.0.1", EVENTNAME_ALL, true, "localhost",
false, true, 0, true);
ips_add(IPS_GROUP_OK, "127.0.0.1", OVENTNAME_ALL, false, "localhost",
false, true, 0, true);
K_WUNLOCK(ips_free);
events_free = k_new_list("Events", sizeof(EVENTS), events_free = k_new_list("Events", sizeof(EVENTS),
ALLOC_EVENTS, LIMIT_EVENTS, true); ALLOC_EVENTS, LIMIT_EVENTS, true);
@ -2785,8 +2791,7 @@ static enum cmd_values breakdown(K_ITEM **ml_item, char *buf, tv_t *now,
TRANSFER *transfer; TRANSFER *transfer;
K_TREE_CTX ctx[1]; K_TREE_CTX ctx[1];
MSGLINE *msgline; MSGLINE *msgline;
K_ITEM *t_item = NULL, *cd_item = NULL, *seqall, *i_item; K_ITEM *t_item = NULL, *cd_item = NULL, *seqall;
IPS *ips;
char *cmdptr, *idptr, *next, *eq, *end, *was; char *cmdptr, *idptr, *next, *eq, *end, *was;
char *data = NULL, *st = NULL, *st2 = NULL, *ip = NULL; char *data = NULL, *st = NULL, *st2 = NULL, *ip = NULL;
bool noid = false; bool noid = false;
@ -3106,27 +3111,12 @@ static enum cmd_values breakdown(K_ITEM **ml_item, char *buf, tv_t *now,
free(cmdptr); free(cmdptr);
if (!seqall && ip) { if (!seqall && ip) {
bool alert = false; bool alert, is_event;
K_WLOCK(ips_free); K_WLOCK(ips_free);
i_item = find_ips(IPS_GROUP_BAN, ip); alert = banned_ips(ip, now, &is_event);
if (i_item) {
DATA_IPS(ips, i_item);
// Has the ban expired? 0=eternal
if (ips->lifetime > 0 &&
(int)tvdiff(now, &(ips->createdate)) > ips->lifetime) {
remove_from_ktree(ips_root, i_item);
k_unlink_item(ips_store, i_item);
if (ips->description) {
LIST_MEM_SUB(ips_free, ips->description);
FREENULL(ips->description);
}
k_add_head(ips_free, i_item);
} else
alert = true;
}
K_WUNLOCK(ips_free); K_WUNLOCK(ips_free);
if (alert) if (alert)
return CMD_ALERT; return is_event ? CMD_ALERTEVENT : CMD_ALERTOVENT;
} }
return ckdb_cmds[msgline->which_cmds].cmd_val; return ckdb_cmds[msgline->which_cmds].cmd_val;
@ -4322,12 +4312,16 @@ static void *socketer(__maybe_unused void *arg)
now.tv_sec); now.tv_sec);
send_unix_msg(sockd, reply); send_unix_msg(sockd, reply);
break; break;
case CMD_ALERT: case CMD_ALERTEVENT:
case CMD_ALERTOVENT:
snprintf(reply, sizeof(reply), snprintf(reply, sizeof(reply),
"%s.%ld.failed.ERR", "%s.%ld.failed.ERR",
msgline->id, msgline->id,
now.tv_sec); now.tv_sec);
if (cmdnum == CMD_ALERTEVENT)
tmp = reply_event(EVENTID_NONE, reply); tmp = reply_event(EVENTID_NONE, reply);
else
tmp = reply_ovent(OVENTID_NONE, reply);
send_unix_msg(sockd, tmp); send_unix_msg(sockd, tmp);
FREENULL(tmp); FREENULL(tmp);
break; break;
@ -4654,7 +4648,8 @@ static void reload_line(PGconn *conn, char *filename, uint64_t count, char *buf)
switch (cmdnum) { switch (cmdnum) {
// Ignore // Ignore
case CMD_REPLY: case CMD_REPLY:
case CMD_ALERT: case CMD_ALERTEVENT:
case CMD_ALERTOVENT:
break; break;
// Shouldn't be there // Shouldn't be there
case CMD_TERMINATE: case CMD_TERMINATE:

36
src/ckdb.h

@ -51,7 +51,7 @@
#define DB_VLOCK "1" #define DB_VLOCK "1"
#define DB_VERSION "1.0.4" #define DB_VERSION "1.0.4"
#define CKDB_VERSION DB_VERSION"-1.953" #define CKDB_VERSION DB_VERSION"-1.954"
#define WHERE_FFL " - from %s %s() line %d" #define WHERE_FFL " - from %s %s() line %d"
#define WHERE_FFL_HERE __FILE__, __func__, __LINE__ #define WHERE_FFL_HERE __FILE__, __func__, __LINE__
@ -632,7 +632,8 @@ enum cmd_values {
CMD_UNSET, CMD_UNSET,
CMD_DUPSEQ, // Ignore, we've already got it CMD_DUPSEQ, // Ignore, we've already got it
CMD_REPLY, // Means something was wrong - send back reply CMD_REPLY, // Means something was wrong - send back reply
CMD_ALERT, // Means reply with the buf passed CMD_ALERTEVENT, // Means reply with the buf passed
CMD_ALERTOVENT, // Means reply with the buf passed
CMD_TERMINATE, CMD_TERMINATE,
CMD_PING, CMD_PING,
CMD_VERSION, CMD_VERSION,
@ -1962,6 +1963,8 @@ extern K_LIST *process_pplns_free;
typedef struct ips { typedef struct ips {
char group[TXT_SML+1]; char group[TXT_SML+1];
char ip[TXT_MED+1]; char ip[TXT_MED+1];
char eventname[TXT_SML+1];
bool is_event;
int lifetime; int lifetime;
bool log; bool log;
char *description; char *description;
@ -1978,6 +1981,13 @@ extern K_TREE *ips_root;
extern K_LIST *ips_free; extern K_LIST *ips_free;
extern K_STORE *ips_store; extern K_STORE *ips_store;
// Only used by OK
#define EVENTNAME_ALL "*E"
#define OVENTNAME_ALL "*O"
// All eventnames will be less than this
#define EVENTNAME_MAX "~"
#define IPS_GROUP_OK "OK" #define IPS_GROUP_OK "OK"
#define IPS_GROUP_BAD "BAD" #define IPS_GROUP_BAD "BAD"
#define IPS_GROUP_BAN "BAN" #define IPS_GROUP_BAN "BAN"
@ -2823,7 +2833,15 @@ extern K_ITEM *find_payouts_wid(int64_t workinfoidend, K_TREE_CTX *ctx);
extern double payout_stats(PAYOUTS *payouts, char *statname); extern double payout_stats(PAYOUTS *payouts, char *statname);
extern bool process_pplns(int32_t height, char *blockhash, tv_t *now); extern bool process_pplns(int32_t height, char *blockhash, tv_t *now);
extern cmp_t cmp_ips(K_ITEM *a, K_ITEM *b); extern cmp_t cmp_ips(K_ITEM *a, K_ITEM *b);
extern K_ITEM *find_ips(char *group, char *ip); extern bool _is_limitname(bool is_event, char *eventname, bool allow_all);
#define is_elimitname(_name, _all) _is_limitname(true, _name, _all)
#define is_olimitname(_name, _all) _is_limitname(false, _name, _all)
extern K_ITEM *find_ips(char *group, char *ip, char *eventname, K_TREE_CTX *ctx);
extern K_ITEM *last_ips(char *group, char *ip, K_TREE_CTX *ctx);
extern bool _ok_ips(bool is_event, char *ip, char *eventname, tv_t *now);
#define ok_ips_event(_ip, _name, _now) _ok_ips(true, _ip, _name, _now)
#define ok_ips_ovent(_ip, _name, _now) _ok_ips(false, _ip, _name, _now)
extern bool banned_ips(char *ip, tv_t *now, bool *is_event);
extern cmp_t cmp_events_user(K_ITEM *a, K_ITEM *b); extern cmp_t cmp_events_user(K_ITEM *a, K_ITEM *b);
extern cmp_t cmp_events_ip(K_ITEM *a, K_ITEM *b); extern cmp_t cmp_events_ip(K_ITEM *a, K_ITEM *b);
extern cmp_t cmp_events_ipc(K_ITEM *a, K_ITEM *b); extern cmp_t cmp_events_ipc(K_ITEM *a, K_ITEM *b);
@ -2833,9 +2851,11 @@ extern K_ITEM *last_events_ip(int id, char *ip, K_TREE_CTX *ctx);
extern K_ITEM *last_events_ipc(int id, char *ipc, K_TREE_CTX *ctx); extern K_ITEM *last_events_ipc(int id, char *ipc, K_TREE_CTX *ctx);
extern K_ITEM *last_events_hash(int id, char *hash, K_TREE_CTX *ctx); extern K_ITEM *last_events_hash(int id, char *hash, K_TREE_CTX *ctx);
extern int check_events(EVENTS *events); extern int check_events(EVENTS *events);
extern char *_reply_event(int event, char *buf, bool fre); extern char *_reply_event(bool is_event, int event, char *buf, bool fre);
#define reply_event(_event, _buf) _reply_event(_event, _buf, false) #define reply_event(_event, _buf) _reply_event(true, _event, _buf, false)
#define reply_event_free(_event, _buf) _reply_event(_event, _buf, true) #define reply_event_free(_event, _buf) _reply_event(true, _event, _buf, true)
#define reply_ovent(_event, _buf) _reply_event(false, _event, _buf, false)
#define reply_ovent_free(_event, _buf) _reply_event(false, _event, _buf, true)
extern cmp_t cmp_ovents(K_ITEM *a, K_ITEM *b); extern cmp_t cmp_ovents(K_ITEM *a, K_ITEM *b);
extern K_ITEM *find_ovents(char *key, int hour, K_TREE_CTX *ctx); extern K_ITEM *find_ovents(char *key, int hour, K_TREE_CTX *ctx);
extern K_ITEM *last_ovents(char *key, K_TREE_CTX *ctx); extern K_ITEM *last_ovents(char *key, K_TREE_CTX *ctx);
@ -3048,8 +3068,8 @@ extern bool payouts_add(PGconn *conn, bool add, K_ITEM *p_item,
extern K_ITEM *payouts_full_expire(PGconn *conn, int64_t payoutid, tv_t *now, extern K_ITEM *payouts_full_expire(PGconn *conn, int64_t payoutid, tv_t *now,
bool lock); bool lock);
extern bool payouts_fill(PGconn *conn); extern bool payouts_fill(PGconn *conn);
extern void ips_add(char *group, char *ip, char *des, bool log, bool cclass, extern void ips_add(char *group, char *ip, char *eventname, bool is_event,
int life, bool locked); char *des, bool log, bool cclass, int life, bool locked);
extern int _events_add(int id, char *by, char *inet, tv_t *cd, K_TREE *trf_root); extern int _events_add(int id, char *by, char *inet, tv_t *cd, K_TREE *trf_root);
#define events_add(_id, _trf_root) _events_add(_id, NULL, NULL, NULL, _trf_root) #define events_add(_id, _trf_root) _events_add(_id, NULL, NULL, NULL, _trf_root)
extern bool auths_add(PGconn *conn, char *poolinstance, char *username, extern bool auths_add(PGconn *conn, char *poolinstance, char *username,

50
src/ckdb_cmd.c

@ -7537,10 +7537,11 @@ static char *cmd_events(__maybe_unused PGconn *conn, char *cmd, char *id,
__maybe_unused char *code, __maybe_unused char *inet, __maybe_unused char *code, __maybe_unused char *inet,
__maybe_unused tv_t *cd, K_TREE *trf_root) __maybe_unused tv_t *cd, K_TREE *trf_root)
{ {
K_ITEM *i_action, *i_cmd, *i_list, *i_ip, *i_lifetime, *i_des, *i_item; K_ITEM *i_action, *i_cmd, *i_list, *i_ip, *i_eventname, *i_lifetime;
K_ITEM *i_des, *i_item;
K_TREE_CTX ctx[1]; K_TREE_CTX ctx[1];
IPS *ips; IPS *ips;
char *action, *alert_cmd, *list, *ip, *des; char *action, *alert_cmd, *list, *ip, *eventname, *des;
char reply[1024] = ""; char reply[1024] = "";
size_t siz = sizeof(reply); size_t siz = sizeof(reply);
char tmp[1024] = ""; char tmp[1024] = "";
@ -7683,7 +7684,7 @@ static char *cmd_events(__maybe_unused PGconn *conn, char *cmd, char *id,
snprintf(tmp, sizeof(tmp), "rows=%d", rows); snprintf(tmp, sizeof(tmp), "rows=%d", rows);
APPEND_REALLOC(buf, off, len, tmp); APPEND_REALLOC(buf, off, len, tmp);
} else if (strcasecmp(action, "ban") == 0) { } else if (strcasecmp(action, "ban") == 0) {
/* Ban the ip with optional lifetime /* Ban the ip with optional eventname and lifetime
* N.B. this doesn't survive a CKDB restart * N.B. this doesn't survive a CKDB restart
* use just cmd_setopts for permanent bans */ * use just cmd_setopts for permanent bans */
bool found = false; bool found = false;
@ -7692,6 +7693,14 @@ static char *cmd_events(__maybe_unused PGconn *conn, char *cmd, char *id,
if (!i_ip) if (!i_ip)
return strdup(reply); return strdup(reply);
ip = transfer_data(i_ip); ip = transfer_data(i_ip);
i_eventname = optional_name(trf_root, "eventname", 1, NULL, reply, siz);
if (i_eventname)
eventname = transfer_data(i_eventname);
else {
if (*reply)
return strdup(reply);
eventname = EVENTNAME_ALL;
}
i_lifetime = optional_name(trf_root, "lifetime", 1, i_lifetime = optional_name(trf_root, "lifetime", 1,
(char *)intpatt, reply, siz); (char *)intpatt, reply, siz);
if (i_lifetime) if (i_lifetime)
@ -7711,10 +7720,10 @@ static char *cmd_events(__maybe_unused PGconn *conn, char *cmd, char *id,
des = NULL; des = NULL;
} }
K_WLOCK(ips_free); K_WLOCK(ips_free);
i_item = find_ips(IPS_GROUP_BAN, ip); i_item = find_ips(IPS_GROUP_BAN, ip, eventname, NULL);
if (i_item) { if (i_item) {
found = true;
DATA_IPS(ips, i_item); DATA_IPS(ips, i_item);
found = true;
oldlife = ips->lifetime; oldlife = ips->lifetime;
ips->lifetime = lifetime; ips->lifetime = lifetime;
// Don't change it if it's not supplied // Don't change it if it's not supplied
@ -7725,20 +7734,23 @@ static char *cmd_events(__maybe_unused PGconn *conn, char *cmd, char *id,
LIST_MEM_ADD(ips_free, ips->description); LIST_MEM_ADD(ips_free, ips->description);
} }
} else { } else {
ips_add(IPS_GROUP_BAN, ip, des, true, false, ips_add(IPS_GROUP_BAN, ip, eventname,
lifetime, true); is_elimitname(eventname, true), des, true,
false, lifetime, true);
} }
K_WUNLOCK(ips_free); K_WUNLOCK(ips_free);
APPEND_REALLOC_INIT(buf, off, len); APPEND_REALLOC_INIT(buf, off, len);
APPEND_REALLOC(buf, off, len, "ok."); APPEND_REALLOC(buf, off, len, "ok.");
if (found) { if (found) {
snprintf(tmp, sizeof(tmp), "already %s %d->%d", snprintf(tmp, sizeof(tmp), "already %s/%s %d->%d",
ip, oldlife, lifetime); ip, eventname, oldlife, lifetime);
} else } else {
snprintf(tmp, sizeof(tmp), "ban %s %d", ip, lifetime); snprintf(tmp, sizeof(tmp), "ban %s/%s %d",
ip, eventname, lifetime);
}
APPEND_REALLOC(buf, off, len, tmp); APPEND_REALLOC(buf, off, len, tmp);
} else if (strcasecmp(action, "unban") == 0) { } else if (strcasecmp(action, "unban") == 0) {
/* Unban the ip - sets lifetime to 1 meaning /* Unban the ip+eventname - sets lifetime to 1 meaning
* it expires 1 second after it was created * it expires 1 second after it was created
* so next access will remove the ban and succeed * so next access will remove the ban and succeed
* N.B. if it was a permanent 'cmd_setopts' ban, the unban * N.B. if it was a permanent 'cmd_setopts' ban, the unban
@ -7752,8 +7764,12 @@ static char *cmd_events(__maybe_unused PGconn *conn, char *cmd, char *id,
if (!i_ip) if (!i_ip)
return strdup(reply); return strdup(reply);
ip = transfer_data(i_ip); ip = transfer_data(i_ip);
i_eventname = require_name(trf_root, "eventname", 1, NULL, reply, siz);
if (!i_eventname)
return strdup(reply);
eventname = transfer_data(i_eventname);
K_WLOCK(ips_free); K_WLOCK(ips_free);
i_item = find_ips(IPS_GROUP_BAN, ip); i_item = find_ips(IPS_GROUP_BAN, ip, eventname, NULL);
if (i_item) { if (i_item) {
found = true; found = true;
DATA_IPS(ips, i_item); DATA_IPS(ips, i_item);
@ -7764,9 +7780,13 @@ static char *cmd_events(__maybe_unused PGconn *conn, char *cmd, char *id,
if (found) { if (found) {
APPEND_REALLOC(buf, off, len, "ok."); APPEND_REALLOC(buf, off, len, "ok.");
APPEND_REALLOC(buf, off, len, ip); APPEND_REALLOC(buf, off, len, ip);
APPEND_REALLOC(buf, off, len, "/");
APPEND_REALLOC(buf, off, len, eventname);
APPEND_REALLOC(buf, off, len, " unbanned"); APPEND_REALLOC(buf, off, len, " unbanned");
} else } else {
APPEND_REALLOC(buf, off, len, "ERR.unknown ip"); APPEND_REALLOC(buf, off, len,
"ERR.unknown ip+eventname");
}
} else { } else {
snprintf(reply, siz, "unknown action '%s'", action); snprintf(reply, siz, "unknown action '%s'", action);
LOGERR("%s() %s.%s", __func__, id, reply); LOGERR("%s() %s.%s", __func__, id, reply);

190
src/ckdb_data.c

@ -4273,7 +4273,7 @@ oku:
return ok; return ok;
} }
// order by group asc,ip asc,expirydate desc // order by group asc,ip asc,eventname asc,expirydate desc
cmp_t cmp_ips(K_ITEM *a, K_ITEM *b) cmp_t cmp_ips(K_ITEM *a, K_ITEM *b)
{ {
IPS *ia, *ib; IPS *ia, *ib;
@ -4282,21 +4282,52 @@ cmp_t cmp_ips(K_ITEM *a, K_ITEM *b)
cmp_t c = CMP_STR(ia->group, ib->group); cmp_t c = CMP_STR(ia->group, ib->group);
if (c == 0) { if (c == 0) {
c = CMP_STR(ia->ip, ib->ip); c = CMP_STR(ia->ip, ib->ip);
if (c == 0) {
c = CMP_STR(ia->eventname, ib->eventname);
if (c == 0) if (c == 0)
c = CMP_TV(ib->expirydate, ia->expirydate); c = CMP_TV(ib->expirydate, ia->expirydate);
} }
}
return c; return c;
} }
bool _is_limitname(bool is_event, char *eventname, bool allow_all)
{
int i;
if (is_event) {
if (allow_all && strcmp(eventname, EVENTNAME_ALL) == 0)
return true;
i = -1;
while (e_limits[++i].name) {
if (strcmp(eventname, e_limits[i].name) == 0)
return true;
}
} else {
if (allow_all && strcmp(eventname, OVENTNAME_ALL) == 0)
return true;
i = -1;
while (o_limits[++i].name) {
if (strcmp(eventname, o_limits[i].name) == 0)
return true;
}
}
return false;
}
// Must be R or W locked before call // Must be R or W locked before call
K_ITEM *find_ips(char *group, char *ip) K_ITEM *find_ips(char *group, char *ip, char *eventname, K_TREE_CTX *ctx)
{ {
K_TREE_CTX ctx[1]; K_TREE_CTX ctx0[1];
K_ITEM look; K_ITEM look;
IPS ips; IPS ips;
if (ctx == NULL)
ctx = ctx0;
STRNCPY(ips.group, group); STRNCPY(ips.group, group);
STRNCPY(ips.ip, ip); STRNCPY(ips.ip, ip);
STRNCPY(ips.eventname, eventname);
ips.expirydate.tv_sec = default_expiry.tv_sec; ips.expirydate.tv_sec = default_expiry.tv_sec;
ips.expirydate.tv_usec = default_expiry.tv_usec; ips.expirydate.tv_usec = default_expiry.tv_usec;
@ -4305,6 +4336,104 @@ K_ITEM *find_ips(char *group, char *ip)
return find_in_ktree(ips_root, &look, ctx); return find_in_ktree(ips_root, &look, ctx);
} }
K_ITEM *last_ips(char *group, char *ip, K_TREE_CTX *ctx)
{
K_TREE_CTX ctx0[1];
K_ITEM look;
IPS ips;
if (ctx == NULL)
ctx = ctx0;
STRNCPY(ips.group, group);
STRNCPY(ips.ip, ip);
STRNCPY(ips.eventname, EVENTNAME_MAX);
copy_tv(&(ips.expirydate), &default_expiry);
INIT_IPS(&look);
look.data = (void *)(&ips);
return find_before_in_ktree(ips_root, &look, ctx);
}
// IPS override checking eventname
bool _ok_ips(bool is_event, char *ip, char *eventname, tv_t *now)
{
K_TREE_CTX ctx[1];
K_ITEM *i_item = NULL, *prev_item;
bool ret = false;
IPS *ips;
i_item = last_ips(IPS_GROUP_OK, ip, ctx);
DATA_IPS_NULL(ips, i_item);
while (i_item && strcmp(ips->group, IPS_GROUP_OK) == 0 &&
strcmp(ips->ip, ip) == 0) {
if (CURRENT(&(ips->expirydate)) &&
(strcmp(ips->eventname, eventname) == 0 ||
(is_event && strcmp(ips->eventname, EVENTNAME_ALL) == 0) ||
(!is_event && strcmp(ips->eventname, OVENTNAME_ALL) == 0))) {
if (ips->lifetime == 0 ||
(int)tvdiff(now, &(ips->createdate)) <= ips->lifetime) {
ret = true;
break;
}
// The OK has expired, so remove it
prev_item = prev_in_ktree(ctx);
k_unlink_item(ips_store, i_item);
if (ips->description) {
LIST_MEM_SUB(ips_free, ips->description);
FREENULL(ips->description);
}
k_add_head(ips_free, i_item);
i_item = prev_item;
DATA_IPS_NULL(ips, i_item);
continue;
}
i_item = prev_in_ktree(ctx);
DATA_IPS_NULL(ips, i_item);
}
return ret;
}
/* Must be W locked before call
* N.B. a ban will ban an OK ip if both BAN and OK exist */
bool banned_ips(char *ip, tv_t *now, bool *is_event)
{
K_TREE_CTX ctx[1];
K_ITEM *i_item = NULL, *prev_item;
bool ret = false;
IPS *ips;
i_item = last_ips(IPS_GROUP_BAN, ip, ctx);
DATA_IPS_NULL(ips, i_item);
while (i_item && strcmp(ips->group, IPS_GROUP_BAN) == 0 &&
strcmp(ips->ip, ip) == 0) {
if (CURRENT(&(ips->expirydate))) {
// Any current unexpired ban
if (ips->lifetime == 0 ||
(int)tvdiff(now, &(ips->createdate)) <= ips->lifetime) {
if (is_event)
*is_event = ips->is_event;
ret = true;
break;
}
// The ban has expired, so remove it
prev_item = prev_in_ktree(ctx);
k_unlink_item(ips_store, i_item);
if (ips->description) {
LIST_MEM_SUB(ips_free, ips->description);
FREENULL(ips->description);
}
k_add_head(ips_free, i_item);
i_item = prev_item;
DATA_IPS_NULL(ips, i_item);
continue;
}
i_item = prev_in_ktree(ctx);
DATA_IPS_NULL(ips, i_item);
}
return ret;
}
// order by createby asc,id asc,expirydate desc, createdate asc // order by createby asc,id asc,expirydate desc, createdate asc
cmp_t cmp_events_user(K_ITEM *a, K_ITEM *b) cmp_t cmp_events_user(K_ITEM *a, K_ITEM *b)
{ {
@ -4498,13 +4627,13 @@ static const char *cause_str(enum event_cause cause)
} }
} }
// return EVENT_OK or -timeout seconds // return EVENT_OK or timeout seconds
int check_events(EVENTS *events) int check_events(EVENTS *events)
{ {
bool alert = false, user1, user2; bool alert = false, ok, user1, user2;
char createby[TXT_SML+1], *st = NULL; char createby[TXT_SML+1], *st = NULL;
enum event_cause cause = CAUSE_NONE; enum event_cause cause = CAUSE_NONE;
K_ITEM *i_item, *e_item = NULL, *tmp_item, *u_item; K_ITEM *e_item = NULL, *tmp_item, *u_item;
K_TREE_CTX ctx[1]; K_TREE_CTX ctx[1];
EVENTS *e = NULL; EVENTS *e = NULL;
char cmd[MAX_ALERT_CMD+1]; char cmd[MAX_ALERT_CMD+1];
@ -4524,16 +4653,17 @@ int check_events(EVENTS *events)
if (!cmd[0]) if (!cmd[0])
return EVENT_OK; return EVENT_OK;
K_RLOCK(ips_free); setnow(&now);
i_item = find_ips(IPS_GROUP_OK, events->createinet);
if (!i_item) K_WLOCK(ips_free);
i_item = find_ips(IPS_GROUP_OK, events->ipc); ok = ok_ips_event(events->createinet, e_limits[events->id].name, &now);
K_RUNLOCK(ips_free); if (!ok)
if (i_item) ok = ok_ips_event(events->ipc, e_limits[events->id].name, &now);
K_WUNLOCK(ips_free);
if (ok)
return EVENT_OK; return EVENT_OK;
// All tests below always run all full checks to clean up old events // All tests below always run all full checks to clean up old events
setnow(&now);
K_WLOCK(events_free); K_WLOCK(events_free);
K_RLOCK(event_limits_free); K_RLOCK(event_limits_free);
// Check hash - same hash passfail on more than one valid User // Check hash - same hash passfail on more than one valid User
@ -4765,7 +4895,7 @@ int check_events(EVENTS *events)
st = safe_text_nonull(events->createby), st = safe_text_nonull(events->createby),
cause_str(cause)); cause_str(cause));
FREENULL(st); FREENULL(st);
ips_add(IPS_GROUP_BAN, events->createinet, ips_add(IPS_GROUP_BAN, events->createinet, name, true,
(char *)cause_str(cause), true, false, lifetime, false); (char *)cause_str(cause), true, false, lifetime, false);
pid = fork(); pid = fork();
if (pid < 0) { if (pid < 0) {
@ -4788,7 +4918,7 @@ int check_events(EVENTS *events)
exit(0); exit(0);
} }
} }
return -lifetime; return lifetime;
} }
return EVENT_OK; return EVENT_OK;
} }
@ -4796,11 +4926,11 @@ int check_events(EVENTS *events)
static char lurt[] = "alert="; static char lurt[] = "alert=";
static size_t lurtsiz = sizeof(lurt); static size_t lurtsiz = sizeof(lurt);
static char tmf[] = "Too many failures, come back later"; static char tmf[] = "Too many failures, come back later";
static size_t tmfsiz = sizeof(tmf); static size_t tmfsiz = sizeof(tmf); // includes null
static char tma[] = "Too many accesses, come back later"; static char tma[] = "Too many accesses, come back later";
static size_t tmasiz = sizeof(tma); static size_t tmasiz = sizeof(tma); // includes null
char *_reply_event(int event, char *buf, bool fre) char *_reply_event(bool is_event, int event, char *buf, bool fre)
{ {
size_t len; size_t len;
char *reply; char *reply;
@ -4818,7 +4948,7 @@ char *_reply_event(int event, char *buf, bool fre)
len = strlen(buf); len = strlen(buf);
len += 1 + lurtsiz; len += 1 + lurtsiz;
if (event < 0) if (is_event)
len += tmfsiz; len += tmfsiz;
else else
len += tmasiz; len += tmasiz;
@ -4826,7 +4956,7 @@ char *_reply_event(int event, char *buf, bool fre)
if (!reply) if (!reply)
quithere(1, "malloc (%d) OOM", (int)len); quithere(1, "malloc (%d) OOM", (int)len);
snprintf(reply, len, "%s%c%s%s", buf, FLDSEP, lurt, snprintf(reply, len, "%s%c%s%s", buf, FLDSEP, lurt,
event < 0 ? tmf : tma); is_event ? tmf : tma);
if (fre) if (fre)
free(buf); free(buf);
return reply; return reply;
@ -4959,9 +5089,8 @@ static enum was_alert check_one_ovent(int id, char *key, tv_t *now,
// return OVENT_OK or +timeout seconds // return OVENT_OK or +timeout seconds
int check_ovents(int id, char *u_key, char *i_key, char *c_key, tv_t *now) int check_ovents(int id, char *u_key, char *i_key, char *c_key, tv_t *now)
{ {
K_ITEM *i_item;
enum was_alert was; enum was_alert was;
bool alert = false; bool alert = false, ok;
char *st = NULL; char *st = NULL;
enum event_cause cause = CAUSE_NONE; enum event_cause cause = CAUSE_NONE;
char cmd[MAX_ALERT_CMD+1]; char cmd[MAX_ALERT_CMD+1];
@ -4980,12 +5109,12 @@ int check_ovents(int id, char *u_key, char *i_key, char *c_key, tv_t *now)
return OVENT_OK; return OVENT_OK;
if (i_key[0]) { if (i_key[0]) {
K_RLOCK(ips_free); K_WLOCK(ips_free);
i_item = find_ips(IPS_GROUP_OK, i_key); ok = ok_ips_ovent(i_key, o_limits[id].name, now);
if (!i_item) if (!ok && c_key[0])
i_item = find_ips(IPS_GROUP_OK, i_key); ok = ok_ips_ovent(c_key, o_limits[id].name, now);
K_RUNLOCK(ips_free); K_WUNLOCK(ips_free);
if (i_item) if (ok)
return OVENT_OK; return OVENT_OK;
} }
@ -5076,8 +5205,9 @@ int check_ovents(int id, char *u_key, char *i_key, char *c_key, tv_t *now)
__func__, id, st = safe_text(u_key)); __func__, id, st = safe_text(u_key));
FREENULL(st); FREENULL(st);
} else { } else {
ips_add(IPS_GROUP_BAN, i_key, (char *)cause_str(cause), ips_add(IPS_GROUP_BAN, i_key, name, false,
true, false, lifetime, false); (char *)cause_str(cause), true, false,
lifetime, false);
pid = fork(); pid = fork();
if (pid < 0) { if (pid < 0) {
LOGERR("%s() OLERT failed to fork (%d)", LOGERR("%s() OLERT failed to fork (%d)",

60
src/ckdb_dbio.c

@ -2457,7 +2457,7 @@ void oc_diff_percent(OPTIONCONTROL *oc, __maybe_unused const char *from)
* Item is one of the field names in event_limits * Item is one of the field names in event_limits
* e.g. user_low_time, user_low_time_limit etc * e.g. user_low_time, user_low_time_limit etc
* as below in the if tests * as below in the if tests
* lifetime values can't = -EVENT_OK */ * lifetime values can't = EVENT_OK */
void oc_event_limits(OPTIONCONTROL *oc, const char *from) void oc_event_limits(OPTIONCONTROL *oc, const char *from)
{ {
bool processed = false; bool processed = false;
@ -2491,12 +2491,12 @@ void oc_event_limits(OPTIONCONTROL *oc, const char *from)
} else if (strcmp(ptr2, "ip_hi_time_limit") == 0) { } else if (strcmp(ptr2, "ip_hi_time_limit") == 0) {
e_limits[i].ip_hi_time_limit = val; e_limits[i].ip_hi_time_limit = val;
} else if (strcmp(ptr2, "lifetime") == 0) { } else if (strcmp(ptr2, "lifetime") == 0) {
if (val != -(EVENT_OK)) if (val != EVENT_OK)
e_limits[i].lifetime = val; e_limits[i].lifetime = val;
else { else {
LOGERR("%s(%s): ERR: lifetime can't be" LOGERR("%s(%s): ERR: lifetime can't be"
" %d in '%s'", " %d in '%s'",
from, __func__, -(EVENT_OK), from, __func__, EVENT_OK,
oc->optionname); oc->optionname);
} }
} else { } else {
@ -2511,12 +2511,12 @@ void oc_event_limits(OPTIONCONTROL *oc, const char *from)
} }
if (!processed) { if (!processed) {
if (strcmp(ptr, "hash_lifetime") == 0) { if (strcmp(ptr, "hash_lifetime") == 0) {
if (val != -(EVENT_OK)) if (val != EVENT_OK)
event_limits_hash_lifetime = val; event_limits_hash_lifetime = val;
else { else {
LOGERR("%s(%s): ERR: lifetime can't be" LOGERR("%s(%s): ERR: lifetime can't be"
" %d in '%s'", " %d in '%s'",
from, __func__, -(EVENT_OK), from, __func__, EVENT_OK,
oc->optionname); oc->optionname);
} }
processed = true; processed = true;
@ -2610,18 +2610,36 @@ void oc_ovent_limits(OPTIONCONTROL *oc, const char *from)
/* IPS for IPS_GROUP_OK/BAN look like: /* IPS for IPS_GROUP_OK/BAN look like:
* optionname: (OC_IPS_OK or OC_IPS_BAN) + description * optionname: (OC_IPS_OK or OC_IPS_BAN) + description
* optionvalue: is the IP address * optionvalue: is the IP address:EVENTNAME
* If you want to add the cclass subnet of an IP then add it separately * If you want to add the cclass subnet of an IP then add it separately
* 127.0.0.1 is hard coded OK in ckdb.c */ * 127.0.0.1 is hard coded OK in ckdb.c */
void oc_ips(OPTIONCONTROL *oc, const char *from) void oc_ips(OPTIONCONTROL *oc, const char *from)
{ {
char *colon;
IPS ips;
bool e;
colon = strchr(oc->optionvalue, ':');
if (!colon) {
LOGERR("%s(%s): ERR: Missing ':' after IP '%s' name '%s'",
from, __func__, oc->optionvalue, oc->optionname);
}
STRNCPY(ips.eventname, colon+1);
STRNCPY(ips.ip, oc->optionvalue);
colon = strchr(ips.ip, ':');
if (colon)
*colon = '\0';
if (strncmp(oc->optionname, OC_IPS_OK, strlen(OC_IPS_OK)) == 0) { if (strncmp(oc->optionname, OC_IPS_OK, strlen(OC_IPS_OK)) == 0) {
ips_add(IPS_GROUP_OK, oc->optionvalue, oc->optionname, e = is_elimitname(ips.eventname, true);
false, false, 0, false); ips_add(IPS_GROUP_OK, ips.ip, ips.eventname, e,
oc->optionname, false, false, 0, false);
} else if (strncmp(oc->optionname, OC_IPS_BAN, } else if (strncmp(oc->optionname, OC_IPS_BAN,
strlen(OC_IPS_BAN)) == 0) { strlen(OC_IPS_BAN)) == 0) {
ips_add(IPS_GROUP_BAN, oc->optionvalue, oc->optionname, e = is_elimitname(ips.eventname, true);
true, false, 0, false); ips_add(IPS_GROUP_BAN, ips.ip, ips.eventname, e,
oc->optionname, false, false, 0, false);
} else { } else {
LOGERR("%s(%s): ERR: Unknown %s name '%s'", LOGERR("%s(%s): ERR: Unknown %s name '%s'",
from, __func__, OC_IPS, oc->optionname); from, __func__, OC_IPS, oc->optionname);
@ -6642,8 +6660,8 @@ int _ovents_add(int id, char *by, char *inet, tv_t *cd, K_TREE *trf_root)
return check_ovents(id, u_key, i_key, c_key, &(ovents.createdate)); return check_ovents(id, u_key, i_key, c_key, &(ovents.createdate));
} }
void ips_add(char *group, char *ip, char *des, bool log, bool cclass, int life, void ips_add(char *group, char *ip, char *eventname, bool is_event, char *des,
bool locked) bool log, bool cclass, int life, bool locked)
{ {
K_ITEM *i_item, *i2_item; K_ITEM *i_item, *i2_item;
IPS *ips, *ips2; IPS *ips, *ips2;
@ -6651,6 +6669,20 @@ void ips_add(char *group, char *ip, char *des, bool log, bool cclass, int life,
tv_t now; tv_t now;
bool ok; bool ok;
if (is_event) {
if (!is_elimitname(eventname, true)) {
LOGERR("%s() invalid Event name '%s' - ignored",
__func__, eventname);
return;
}
} else {
if (!is_olimitname(eventname, true)) {
LOGERR("%s() invalid Ovent name '%s' - ignored",
__func__, eventname);
return;
}
}
setnow(&now); setnow(&now);
if (!locked) if (!locked)
K_WLOCK(ips_free); K_WLOCK(ips_free);
@ -6658,7 +6690,8 @@ void ips_add(char *group, char *ip, char *des, bool log, bool cclass, int life,
DATA_IPS(ips, i_item); DATA_IPS(ips, i_item);
STRNCPY(ips->group, group); STRNCPY(ips->group, group);
STRNCPY(ips->ip, ip); STRNCPY(ips->ip, ip);
ips->lifetime = life; STRNCPY(ips->eventname, eventname);
ips->is_event = is_event;
if (des) { if (des) {
ips->description = strdup(des); ips->description = strdup(des);
if (!ips->description) if (!ips->description)
@ -6666,6 +6699,7 @@ void ips_add(char *group, char *ip, char *des, bool log, bool cclass, int life,
LIST_MEM_ADD(ips_free, ips->description); LIST_MEM_ADD(ips_free, ips->description);
} }
ips->log = log; ips->log = log;
ips->lifetime = life;
HISTORYDATEDEFAULT(ips, &now); HISTORYDATEDEFAULT(ips, &now);
add_to_ktree(ips_root, i_item); add_to_ktree(ips_root, i_item);
k_add_head(ips_store, i_item); k_add_head(ips_store, i_item);

Loading…
Cancel
Save