From 360742bdf4e4aebd80e39a76903c4a8d726f3f44 Mon Sep 17 00:00:00 2001 From: Alexander F?r?y Date: Sat, 27 Feb 2010 01:08:41 +0100 Subject: [PATCH 01/32] Use RPL_QUIETLIST and RPL_ENDOFQUIETLIST instead of RPL_BANLIST and RPL_ENDOFBANLIST for channel mode +q. --- include/numeric.h | 3 +++ src/chmode.c | 9 +++------ src/messages.tab | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/include/numeric.h b/include/numeric.h index d60f283..a85c17e 100644 --- a/include/numeric.h +++ b/include/numeric.h @@ -364,6 +364,9 @@ extern const char *form_str(int); #define RPL_NOTESTLINE 726 #define RPL_TESTMASKGECOS 727 +#define RPL_QUIETLIST 728 +#define RPL_ENDOFQUIETLIST 729 + #define RPL_MONONLINE 730 #define RPL_MONOFFLINE 731 #define RPL_MONLIST 732 diff --git a/src/chmode.c b/src/chmode.c index 23491f7..3161b64 100644 --- a/src/chmode.c +++ b/src/chmode.c @@ -775,8 +775,8 @@ chm_ban(struct Client *source_p, struct Channel *chptr, case CHFL_QUIET: list = &chptr->quietlist; errorval = SM_ERR_RPL_Q; - rpl_list = RPL_BANLIST; - rpl_endlist = RPL_ENDOFBANLIST; + rpl_list = RPL_QUIETLIST; + rpl_endlist = RPL_ENDOFQUIETLIST; mems = ALL_MEMBERS; caps = 0; break; @@ -824,10 +824,7 @@ chm_ban(struct Client *source_p, struct Channel *chptr, me.name, source_p->name, chptr->chname, banptr->banstr, banptr->who, banptr->when); } - if (mode_type == CHFL_QUIET) - sendto_one(source_p, ":%s %d %s %s :End of Channel Quiet List", me.name, rpl_endlist, source_p->name, chptr->chname); - else - sendto_one(source_p, form_str(rpl_endlist), me.name, source_p->name, chptr->chname); + sendto_one(source_p, form_str(rpl_endlist), me.name, source_p->name, chptr->chname); return; } diff --git a/src/messages.tab b/src/messages.tab index 481a0ca..c626aea 100644 --- a/src/messages.tab +++ b/src/messages.tab @@ -749,8 +749,8 @@ static const char * replies[] = { /* 725 RPL_TESTLINE */ ":%s 725 %s %c %ld %s :%s", /* 726 RPL_NOTESTLINE */ ":%s 726 %s %s :No matches", /* 727 RPL_TESTMASKGECOS */ ":%s 727 %s %d %d %s!%s@%s %s :Local/remote clients match", -/* 728 */ NULL, -/* 729 */ NULL, +/* 728 RPL_QUIETLIST */ ":%s 728 %s %s q %s %s %lu", +/* 729 RPL_ENDOFQUIETLIST */ ":%s 729 %s %s q :End of Channel Quiet List", /* 730 RPL_MONONLINE */ ":%s 730 %s :%s", /* 731 RPL_MONOFFLINE */ ":%s 731 %s :%s", /* 732 RPL_MONLIST */ ":%s 732 %s :%s", From bebc68755d618cd2392dd187676128ee32bbee56 Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Sat, 27 Feb 2010 23:56:56 +0100 Subject: [PATCH 02/32] Add a missing comment for new /challenge numerics. --- src/messages.tab | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/messages.tab b/src/messages.tab index c626aea..b8fc7d7 100644 --- a/src/messages.tab +++ b/src/messages.tab @@ -761,8 +761,8 @@ static const char * replies[] = { /* 737 ERR_NOCOMMONCHAN*/ "%s :is in +G mode (server-side ignore) and you do not share a common channel with them.", /* 738 */ NULL, /* 739 */ NULL, -/* 740 */ ":%s 740 %s :%s", -/* 741 */ ":%s 741 %s :End of CHALLENGE", +/* 740 RPL_RSACHALLENGE2*/ ":%s 740 %s :%s", +/* 741 RPL_ENDOFRSACHALLENGE2*/ ":%s 741 %s :End of CHALLENGE", /* 742 */ NULL, /* 743 */ NULL, /* 744 */ NULL, From ce60772db6eb54b5cc87bbaa5c3b5bf783d59be2 Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Sun, 28 Feb 2010 00:46:56 +0100 Subject: [PATCH 03/32] Store the creation time of klines and dlines as a time_t instead of as text. The value 0 indicates the creation time is unknown (currently the case for bandb). Also store a creation time for xlines and resvs, but do not use it yet. --- include/logger.h | 2 +- include/s_conf.h | 1 + modules/m_dline.c | 10 ++++------ modules/m_kline.c | 37 ++++++++++++++++--------------------- modules/m_resv.c | 2 ++ modules/m_xline.c | 1 + src/client.c | 13 +++++++++++-- src/listener.c | 6 +++++- src/logger.c | 6 +++--- src/s_conf.c | 23 +++++++++++++++++++++-- 10 files changed, 65 insertions(+), 36 deletions(-) diff --git a/include/logger.h b/include/logger.h index 6efa0ca..c7f7a6e 100644 --- a/include/logger.h +++ b/include/logger.h @@ -61,7 +61,7 @@ extern void inotice(const char *fmt, ...) AFP(1, 2); extern void iwarn(const char *fmt, ...) AFP(1, 2); extern void ierror(const char *fmt, ...) AFP(1, 2); extern void report_operspy(struct Client *, const char *, const char *); -extern const char *smalldate(void); +extern const char *smalldate(time_t); extern void ilog_error(const char *); #endif diff --git a/include/s_conf.h b/include/s_conf.h index 3ceb2b5..6ca9994 100644 --- a/include/s_conf.h +++ b/include/s_conf.h @@ -69,6 +69,7 @@ struct ConfItem char *user; /* user part of user@host */ int port; time_t hold; /* Hold action until this time (calendar time) */ + time_t created; /* Creation time (for klines etc) */ char *className; /* Name of class */ struct Class *c_class; /* Class of connection */ rb_patricia_node_t *pnode; /* Our patricia node */ diff --git a/modules/m_dline.c b/modules/m_dline.c index 5ac171b..64e5f34 100644 --- a/modules/m_dline.c +++ b/modules/m_dline.c @@ -214,7 +214,6 @@ apply_dline(struct Client *source_p, const char *dlhost, int tdline_time, char * struct ConfItem *aconf; char *oper_reason; char dlbuffer[IRCD_BUFSIZE]; - const char *current_date; struct rb_sockaddr_storage daddr; int t = AF_INET, ty, b; const char *creason; @@ -285,10 +284,10 @@ apply_dline(struct Client *source_p, const char *dlhost, int tdline_time, char * } rb_set_time(); - current_date = smalldate(); aconf = make_conf(); aconf->status = CONF_DLINE; + aconf->created = rb_current_time(); aconf->host = rb_strdup(dlhost); /* Look for an oper reason */ @@ -304,8 +303,8 @@ apply_dline(struct Client *source_p, const char *dlhost, int tdline_time, char * if(tdline_time > 0) { rb_snprintf(dlbuffer, sizeof(dlbuffer), - "Temporary D-line %d min. - %s (%s)", - (int) (tdline_time / 60), reason, current_date); + "Temporary D-line %d min. - %s", + (int) (tdline_time / 60), reason); aconf->passwd = rb_strdup(dlbuffer); aconf->hold = rb_current_time() + tdline_time; add_temp_dline(aconf); @@ -335,8 +334,7 @@ apply_dline(struct Client *source_p, const char *dlhost, int tdline_time, char * } else { - rb_snprintf(dlbuffer, sizeof(dlbuffer), "%s (%s)", reason, current_date); - aconf->passwd = rb_strdup(dlbuffer); + aconf->passwd = rb_strdup(reason); add_conf_by_address(aconf->host, CONF_DLINE, NULL, NULL, aconf); bandb_add(BANDB_DLINE, source_p, aconf->host, NULL, diff --git a/modules/m_kline.c b/modules/m_kline.c index 44012ed..8e72860 100644 --- a/modules/m_kline.c +++ b/modules/m_kline.c @@ -75,9 +75,9 @@ static int valid_wild_card(struct Client *source_p, const char *user, const char static void handle_remote_kline(struct Client *source_p, int tkline_time, const char *user, const char *host, const char *reason); static void apply_kline(struct Client *source_p, struct ConfItem *aconf, - const char *reason, const char *oper_reason, const char *current_date); + const char *reason, const char *oper_reason); static void apply_tkline(struct Client *source_p, struct ConfItem *aconf, - const char *, const char *, const char *, int); + const char *, const char *, int); static int already_placed_kline(struct Client *, const char *, const char *, int); static void handle_remote_unkline(struct Client *source_p, const char *user, const char *host); @@ -101,7 +101,6 @@ mo_kline(struct Client *client_p, struct Client *source_p, int parc, const char char buffer[IRCD_BUFSIZE]; char *reason = def; char *oper_reason; - const char *current_date; const char *target_server = NULL; struct ConfItem *aconf; int tkline_time = 0; @@ -169,9 +168,9 @@ mo_kline(struct Client *client_p, struct Client *source_p, int parc, const char return 0; rb_set_time(); - current_date = smalldate(); aconf = make_conf(); aconf->status = CONF_KILL; + aconf->created = rb_current_time(); aconf->host = rb_strdup(host); aconf->user = rb_strdup(user); aconf->port = 0; @@ -189,16 +188,15 @@ mo_kline(struct Client *client_p, struct Client *source_p, int parc, const char if(tkline_time > 0) { rb_snprintf(buffer, sizeof(buffer), - "Temporary K-line %d min. - %s (%s)", - (int) (tkline_time / 60), reason, current_date); + "Temporary K-line %d min. - %s", + (int) (tkline_time / 60), reason); aconf->passwd = rb_strdup(buffer); - apply_tkline(source_p, aconf, reason, oper_reason, current_date, tkline_time); + apply_tkline(source_p, aconf, reason, oper_reason, tkline_time); } else { - rb_snprintf(buffer, sizeof(buffer), "%s (%s)", reason, current_date); - aconf->passwd = rb_strdup(buffer); - apply_kline(source_p, aconf, reason, oper_reason, current_date); + aconf->passwd = rb_strdup(reason); + apply_kline(source_p, aconf, reason, oper_reason); } if(ConfigFileEntry.kline_delay) @@ -265,7 +263,6 @@ handle_remote_kline(struct Client *source_p, int tkline_time, const char *user, const char *host, const char *kreason) { char buffer[BUFSIZE]; - const char *current_date; char *reason = LOCAL_COPY(kreason); struct ConfItem *aconf = NULL; char *oper_reason; @@ -285,6 +282,7 @@ handle_remote_kline(struct Client *source_p, int tkline_time, aconf = make_conf(); aconf->status = CONF_KILL; + aconf->created = rb_current_time(); aconf->user = rb_strdup(user); aconf->host = rb_strdup(host); @@ -298,21 +296,18 @@ handle_remote_kline(struct Client *source_p, int tkline_time, aconf->spasswd = rb_strdup(oper_reason); } - current_date = smalldate(); - if(tkline_time > 0) { rb_snprintf(buffer, sizeof(buffer), - "Temporary K-line %d min. - %s (%s)", - (int) (tkline_time / 60), reason, current_date); + "Temporary K-line %d min. - %s", + (int) (tkline_time / 60), reason); aconf->passwd = rb_strdup(buffer); - apply_tkline(source_p, aconf, reason, oper_reason, current_date, tkline_time); + apply_tkline(source_p, aconf, reason, oper_reason, tkline_time); } else { - rb_snprintf(buffer, sizeof(buffer), "%s (%s)", reason, current_date); - aconf->passwd = rb_strdup(buffer); - apply_kline(source_p, aconf, reason, oper_reason, current_date); + aconf->passwd = rb_strdup(reason); + apply_kline(source_p, aconf, reason, oper_reason); } if(ConfigFileEntry.kline_delay) @@ -480,7 +475,7 @@ handle_remote_unkline(struct Client *source_p, const char *user, const char *hos */ static void apply_kline(struct Client *source_p, struct ConfItem *aconf, - const char *reason, const char *oper_reason, const char *current_date) + const char *reason, const char *oper_reason) { add_conf_by_address(aconf->host, CONF_KILL, aconf->user, NULL, aconf); bandb_add(BANDB_KLINE, source_p, aconf->user, aconf->host, @@ -517,7 +512,7 @@ apply_kline(struct Client *source_p, struct ConfItem *aconf, */ static void apply_tkline(struct Client *source_p, struct ConfItem *aconf, - const char *reason, const char *oper_reason, const char *current_date, int tkline_time) + const char *reason, const char *oper_reason, int tkline_time) { aconf->hold = rb_current_time() + tkline_time; add_temp_kline(aconf); diff --git a/modules/m_resv.c b/modules/m_resv.c index 21de7f3..16db101 100644 --- a/modules/m_resv.c +++ b/modules/m_resv.c @@ -218,6 +218,7 @@ parse_resv(struct Client *source_p, const char *name, const char *reason, int te aconf = make_conf(); aconf->status = CONF_RESV_CHANNEL; aconf->port = 0; + aconf->created = rb_current_time(); aconf->host = rb_strdup(name); aconf->passwd = rb_strdup(reason); add_to_resv_hash(aconf->host, aconf); @@ -281,6 +282,7 @@ parse_resv(struct Client *source_p, const char *name, const char *reason, int te aconf = make_conf(); aconf->status = CONF_RESV_NICK; aconf->port = 0; + aconf->created = rb_current_time(); aconf->host = rb_strdup(name); aconf->passwd = rb_strdup(reason); rb_dlinkAddAlloc(aconf, &resv_conf_list); diff --git a/modules/m_xline.c b/modules/m_xline.c index 1ff8655..deb441f 100644 --- a/modules/m_xline.c +++ b/modules/m_xline.c @@ -275,6 +275,7 @@ apply_xline(struct Client *source_p, const char *name, const char *reason, int t aconf = make_conf(); aconf->status = CONF_XLINE; + aconf->created = rb_current_time(); aconf->host = rb_strdup(name); aconf->passwd = rb_strdup(reason); collapse(aconf->host); diff --git a/src/client.c b/src/client.c index 1cc32b4..816a5d2 100644 --- a/src/client.c +++ b/src/client.c @@ -423,11 +423,20 @@ notify_banned_client(struct Client *client_p, struct ConfItem *aconf, int ban) static const char k_lined[] = "K-lined"; const char *reason = NULL; const char *exit_reason = conn_closed; + char reasonbuf[BUFSIZE]; if(ConfigFileEntry.kline_with_reason && !EmptyString(aconf->passwd)) { - reason = aconf->passwd; - exit_reason = aconf->passwd; + if(aconf->created) + { + rb_snprintf(reasonbuf, sizeof reasonbuf, "%s (%s)", + aconf->passwd, + smalldate(aconf->created)); + reason = reasonbuf; + } + else + reason = aconf->passwd; + exit_reason = reason; } else { diff --git a/src/listener.c b/src/listener.c index 489aee7..1ac42b0 100644 --- a/src/listener.c +++ b/src/listener.c @@ -480,6 +480,7 @@ accept_precallback(rb_fde_t *F, struct sockaddr *addr, rb_socklen_t addrlen, voi char buf[BUFSIZE]; struct ConfItem *aconf; static time_t last_oper_notice = 0; + int len; if(listener->ssl && (!ssl_ok || !get_ssld_count())) { @@ -519,7 +520,10 @@ accept_precallback(rb_fde_t *F, struct sockaddr *addr, rb_socklen_t addrlen, voi if(ConfigFileEntry.dline_with_reason) { - if (rb_snprintf(buf, sizeof(buf), "ERROR :*** Banned: %s\r\n", aconf->passwd) >= (int)(sizeof(buf)-1)) + len = aconf->created ? + rb_snprintf(buf, sizeof(buf), "ERROR :*** Banned: %s (%s)\r\n", aconf->passwd, smalldate(aconf->created)) : + rb_snprintf(buf, sizeof(buf), "ERROR :*** Banned: %s\r\n", aconf->passwd); + if (len >= (int)(sizeof(buf)-1)) { buf[sizeof(buf) - 3] = '\r'; buf[sizeof(buf) - 2] = '\n'; diff --git a/src/logger.c b/src/logger.c index 53cd72b..bb3f0a6 100644 --- a/src/logger.c +++ b/src/logger.c @@ -180,7 +180,8 @@ ilog(ilogfile dest, const char *format, ...) rb_vsnprintf(buf, sizeof(buf), format, args); va_end(args); - rb_snprintf(buf2, sizeof(buf2), "%s %s\n", smalldate(), buf); + rb_snprintf(buf2, sizeof(buf2), "%s %s\n", + smalldate(rb_current_time()), buf); if(fputs(buf2, logfile) < 0) { @@ -266,11 +267,10 @@ report_operspy(struct Client *source_p, const char *token, const char *arg) } const char * -smalldate(void) +smalldate(time_t ltime) { static char buf[MAX_DATE_STRING]; struct tm *lt; - time_t ltime = rb_current_time(); lt = localtime(<ime); diff --git a/src/s_conf.c b/src/s_conf.c index 4263528..ae83d7a 100644 --- a/src/s_conf.c +++ b/src/s_conf.c @@ -306,6 +306,8 @@ verify_access(struct Client *client_p, const char *username) { struct ConfItem *aconf; char non_ident[USERLEN + 1]; + char reasonbuf[BUFSIZE]; + char *reason; if(IsGotId(client_p)) { @@ -376,9 +378,18 @@ verify_access(struct Client *client_p, const char *username) { if(ConfigFileEntry.kline_with_reason) { + if(aconf->created) + { + snprintf(reasonbuf, sizeof reasonbuf, "%s (%s)", + aconf->passwd, + smalldate(aconf->created)); + reason = reasonbuf; + } + else + reason = aconf->passwd; sendto_one(client_p, form_str(ERR_YOUREBANNEDCREEP), - me.name, client_p->name, aconf->passwd); + me.name, client_p->name, reason); } add_reject(client_p, aconf->user, aconf->host); return (BANNED_CLIENT); @@ -1130,11 +1141,19 @@ get_printable_kline(struct Client *source_p, struct ConfItem *aconf, char **user, char **oper_reason) { static char null[] = ""; + static char reasonbuf[BUFSIZE]; *host = EmptyString(aconf->host) ? null : aconf->host; - *reason = EmptyString(aconf->passwd) ? null : aconf->passwd; *user = EmptyString(aconf->user) ? null : aconf->user; + *reason = EmptyString(aconf->passwd) ? null : aconf->passwd; + if(aconf->created) + { + rb_snprintf(reasonbuf, sizeof reasonbuf, "%s (%s)", + *reason, smalldate(aconf->created)); + *reason = reasonbuf; + } + if(EmptyString(aconf->spasswd) || !IsOper(source_p)) *oper_reason = NULL; else From 157c1f04bd3b04cbdcef5efb3cb280d0e10f1e7f Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Sun, 28 Feb 2010 16:27:06 +0100 Subject: [PATCH 04/32] Generate the "Temporary K-line %d min" part from aconf->hold - aconf->created. --- include/s_conf.h | 1 + modules/m_dline.c | 7 +------ modules/m_kline.c | 22 ++------------------ src/client.c | 13 ++---------- src/listener.c | 4 +--- src/s_conf.c | 53 +++++++++++++++++++++++++++-------------------- 6 files changed, 37 insertions(+), 63 deletions(-) diff --git a/include/s_conf.h b/include/s_conf.h index 6ca9994..4dbdd60 100644 --- a/include/s_conf.h +++ b/include/s_conf.h @@ -349,6 +349,7 @@ extern struct ConfItem *find_tkline(const char *, const char *, struct sockaddr extern char *show_iline_prefix(struct Client *, struct ConfItem *, char *); extern void get_printable_conf(struct ConfItem *, char **, char **, char **, char **, int *, char **); +extern char *get_user_ban_reason(struct ConfItem *aconf); extern void get_printable_kline(struct Client *, struct ConfItem *, char **, char **, char **, char **); diff --git a/modules/m_dline.c b/modules/m_dline.c index 64e5f34..912091c 100644 --- a/modules/m_dline.c +++ b/modules/m_dline.c @@ -213,7 +213,6 @@ apply_dline(struct Client *source_p, const char *dlhost, int tdline_time, char * { struct ConfItem *aconf; char *oper_reason; - char dlbuffer[IRCD_BUFSIZE]; struct rb_sockaddr_storage daddr; int t = AF_INET, ty, b; const char *creason; @@ -289,6 +288,7 @@ apply_dline(struct Client *source_p, const char *dlhost, int tdline_time, char * aconf->status = CONF_DLINE; aconf->created = rb_current_time(); aconf->host = rb_strdup(dlhost); + aconf->passwd = rb_strdup(reason); /* Look for an oper reason */ if((oper_reason = strchr(reason, '|')) != NULL) @@ -302,10 +302,6 @@ apply_dline(struct Client *source_p, const char *dlhost, int tdline_time, char * if(tdline_time > 0) { - rb_snprintf(dlbuffer, sizeof(dlbuffer), - "Temporary D-line %d min. - %s", - (int) (tdline_time / 60), reason); - aconf->passwd = rb_strdup(dlbuffer); aconf->hold = rb_current_time() + tdline_time; add_temp_dline(aconf); @@ -334,7 +330,6 @@ apply_dline(struct Client *source_p, const char *dlhost, int tdline_time, char * } else { - aconf->passwd = rb_strdup(reason); add_conf_by_address(aconf->host, CONF_DLINE, NULL, NULL, aconf); bandb_add(BANDB_DLINE, source_p, aconf->host, NULL, diff --git a/modules/m_kline.c b/modules/m_kline.c index 8e72860..18dbdca 100644 --- a/modules/m_kline.c +++ b/modules/m_kline.c @@ -98,7 +98,6 @@ mo_kline(struct Client *client_p, struct Client *source_p, int parc, const char char def[] = "No Reason"; char user[USERLEN + 2]; char host[HOSTLEN + 2]; - char buffer[IRCD_BUFSIZE]; char *reason = def; char *oper_reason; const char *target_server = NULL; @@ -174,6 +173,7 @@ mo_kline(struct Client *client_p, struct Client *source_p, int parc, const char aconf->host = rb_strdup(host); aconf->user = rb_strdup(user); aconf->port = 0; + aconf->passwd = rb_strdup(reason); /* Look for an oper reason */ if((oper_reason = strchr(reason, '|')) != NULL) @@ -186,18 +186,9 @@ mo_kline(struct Client *client_p, struct Client *source_p, int parc, const char } if(tkline_time > 0) - { - rb_snprintf(buffer, sizeof(buffer), - "Temporary K-line %d min. - %s", - (int) (tkline_time / 60), reason); - aconf->passwd = rb_strdup(buffer); apply_tkline(source_p, aconf, reason, oper_reason, tkline_time); - } else - { - aconf->passwd = rb_strdup(reason); apply_kline(source_p, aconf, reason, oper_reason); - } if(ConfigFileEntry.kline_delay) { @@ -262,7 +253,6 @@ static void handle_remote_kline(struct Client *source_p, int tkline_time, const char *user, const char *host, const char *kreason) { - char buffer[BUFSIZE]; char *reason = LOCAL_COPY(kreason); struct ConfItem *aconf = NULL; char *oper_reason; @@ -285,6 +275,7 @@ handle_remote_kline(struct Client *source_p, int tkline_time, aconf->created = rb_current_time(); aconf->user = rb_strdup(user); aconf->host = rb_strdup(host); + aconf->passwd = rb_strdup(reason); /* Look for an oper reason */ if((oper_reason = strchr(reason, '|')) != NULL) @@ -297,18 +288,9 @@ handle_remote_kline(struct Client *source_p, int tkline_time, } if(tkline_time > 0) - { - rb_snprintf(buffer, sizeof(buffer), - "Temporary K-line %d min. - %s", - (int) (tkline_time / 60), reason); - aconf->passwd = rb_strdup(buffer); apply_tkline(source_p, aconf, reason, oper_reason, tkline_time); - } else - { - aconf->passwd = rb_strdup(reason); apply_kline(source_p, aconf, reason, oper_reason); - } if(ConfigFileEntry.kline_delay) { diff --git a/src/client.c b/src/client.c index 816a5d2..534bec2 100644 --- a/src/client.c +++ b/src/client.c @@ -423,19 +423,10 @@ notify_banned_client(struct Client *client_p, struct ConfItem *aconf, int ban) static const char k_lined[] = "K-lined"; const char *reason = NULL; const char *exit_reason = conn_closed; - char reasonbuf[BUFSIZE]; - if(ConfigFileEntry.kline_with_reason && !EmptyString(aconf->passwd)) + if(ConfigFileEntry.kline_with_reason) { - if(aconf->created) - { - rb_snprintf(reasonbuf, sizeof reasonbuf, "%s (%s)", - aconf->passwd, - smalldate(aconf->created)); - reason = reasonbuf; - } - else - reason = aconf->passwd; + reason = get_user_ban_reason(aconf); exit_reason = reason; } else diff --git a/src/listener.c b/src/listener.c index 1ac42b0..3b8a1fb 100644 --- a/src/listener.c +++ b/src/listener.c @@ -520,9 +520,7 @@ accept_precallback(rb_fde_t *F, struct sockaddr *addr, rb_socklen_t addrlen, voi if(ConfigFileEntry.dline_with_reason) { - len = aconf->created ? - rb_snprintf(buf, sizeof(buf), "ERROR :*** Banned: %s (%s)\r\n", aconf->passwd, smalldate(aconf->created)) : - rb_snprintf(buf, sizeof(buf), "ERROR :*** Banned: %s\r\n", aconf->passwd); + len = rb_snprintf(buf, sizeof(buf), "ERROR :*** Banned: %s\r\n", get_user_ban_reason(aconf)); if (len >= (int)(sizeof(buf)-1)) { buf[sizeof(buf) - 3] = '\r'; diff --git a/src/s_conf.c b/src/s_conf.c index ae83d7a..c3df6fd 100644 --- a/src/s_conf.c +++ b/src/s_conf.c @@ -306,8 +306,6 @@ verify_access(struct Client *client_p, const char *username) { struct ConfItem *aconf; char non_ident[USERLEN + 1]; - char reasonbuf[BUFSIZE]; - char *reason; if(IsGotId(client_p)) { @@ -377,20 +375,10 @@ verify_access(struct Client *client_p, const char *username) else if(aconf->status & CONF_KILL) { if(ConfigFileEntry.kline_with_reason) - { - if(aconf->created) - { - snprintf(reasonbuf, sizeof reasonbuf, "%s (%s)", - aconf->passwd, - smalldate(aconf->created)); - reason = reasonbuf; - } - else - reason = aconf->passwd; sendto_one(client_p, form_str(ERR_YOUREBANNEDCREEP), - me.name, client_p->name, reason); - } + me.name, client_p->name, + get_user_ban_reason(aconf)); add_reject(client_p, aconf->user, aconf->host); return (BANNED_CLIENT); } @@ -1135,24 +1123,43 @@ get_printable_conf(struct ConfItem *aconf, char **name, char **host, *port = (int) aconf->port; } +char * +get_user_ban_reason(struct ConfItem *aconf) +{ + static char reasonbuf[BUFSIZE]; + + if (aconf->flags & CONF_FLAGS_TEMPORARY && + (aconf->status == CONF_KILL || aconf->status == CONF_DLINE)) + rb_snprintf(reasonbuf, sizeof reasonbuf, + "Temporary %c-line %d min. - ", + aconf->status == CONF_DLINE ? 'D' : 'K', + (aconf->hold - aconf->created) / 60); + else + reasonbuf[0] = '\0'; + if (aconf->passwd) + rb_strlcat(reasonbuf, aconf->passwd, sizeof reasonbuf); + else + rb_strlcat(reasonbuf, "No Reason", sizeof reasonbuf); + if (aconf->created) + { + rb_strlcat(reasonbuf, " (", sizeof reasonbuf); + rb_strlcat(reasonbuf, smalldate(aconf->created), + sizeof reasonbuf); + rb_strlcat(reasonbuf, ")", sizeof reasonbuf); + } + return reasonbuf; +} + void get_printable_kline(struct Client *source_p, struct ConfItem *aconf, char **host, char **reason, char **user, char **oper_reason) { static char null[] = ""; - static char reasonbuf[BUFSIZE]; *host = EmptyString(aconf->host) ? null : aconf->host; *user = EmptyString(aconf->user) ? null : aconf->user; - - *reason = EmptyString(aconf->passwd) ? null : aconf->passwd; - if(aconf->created) - { - rb_snprintf(reasonbuf, sizeof reasonbuf, "%s (%s)", - *reason, smalldate(aconf->created)); - *reason = reasonbuf; - } + *reason = get_user_ban_reason(aconf); if(EmptyString(aconf->spasswd) || !IsOper(source_p)) *oper_reason = NULL; From a0f4c418d39ab72d88e1430500082b7d6bb68073 Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Mon, 1 Mar 2010 01:23:22 +0100 Subject: [PATCH 05/32] Track who set a dline/kline/xline/resv as in ratbox3. Like in ratbox3, there is no way to query this information (other than bandb's tables, but they worked before this commit). --- extensions/m_webirc.c | 2 +- include/operhash.h | 15 +++++ include/s_conf.h | 9 ++- modules/m_dline.c | 2 + modules/m_kline.c | 3 + modules/m_resv.c | 3 + modules/m_testline.c | 2 +- modules/m_xline.c | 3 + src/Makefile.in | 1 + src/bandbi.c | 4 +- src/hostmask.c | 6 +- src/newconf.c | 14 ++--- src/operhash.c | 130 ++++++++++++++++++++++++++++++++++++++++++ src/s_conf.c | 21 ++++--- src/s_user.c | 2 +- 15 files changed, 193 insertions(+), 24 deletions(-) create mode 100644 include/operhash.h create mode 100644 src/operhash.c diff --git a/extensions/m_webirc.c b/extensions/m_webirc.c index c46ce1a..1ddb634 100644 --- a/extensions/m_webirc.c +++ b/extensions/m_webirc.c @@ -91,7 +91,7 @@ mr_webirc(struct Client *client_p, struct Client *source_p, int parc, const char client_p->localClient->ip.ss_family, NULL); if (aconf == NULL || !(aconf->status & CONF_CLIENT)) return 0; - if (!IsConfDoSpoofIp(aconf) || irccmp(aconf->name, "webirc.")) + if (!IsConfDoSpoofIp(aconf) || irccmp(aconf->info.name, "webirc.")) { /* XXX */ sendto_one(source_p, "NOTICE * :Not a CGI:IRC auth block"); diff --git a/include/operhash.h b/include/operhash.h new file mode 100644 index 0000000..643abf9 --- /dev/null +++ b/include/operhash.h @@ -0,0 +1,15 @@ +#ifndef INCLUDED_operhash_h +#define INCLUDED_operhash_h + +struct operhash_entry +{ + char *name; + int refcount; +}; + +void init_operhash(void); +const char *operhash_add(const char *name); +const char *operhash_find(const char *name); +void operhash_delete(const char *name); + +#endif diff --git a/include/s_conf.h b/include/s_conf.h index 4dbdd60..a5ff080 100644 --- a/include/s_conf.h +++ b/include/s_conf.h @@ -60,7 +60,11 @@ struct ConfItem unsigned int status; /* If CONF_ILLEGAL, delete when no clients */ unsigned int flags; int clients; /* Number of *LOCAL* clients using this */ - char *name; /* IRC name, nick, server name, or original u@h */ + union + { + char *name; /* IRC name, nick, server name, or original u@h */ + const char *oper; + } info; char *host; /* host part of user@host */ char *passwd; /* doubles as kline reason *ugh* */ char *spasswd; /* Password to send. */ @@ -112,6 +116,9 @@ struct ConfItem /* Macros for struct ConfItem */ +#define IsConfBan(x) ((x)->status & (CONF_KILL|CONF_XLINE|CONF_DLINE|\ + CONF_RESV_CHANNEL|CONF_RESV_NICK)) + #define IsNoTilde(x) ((x)->flags & CONF_FLAGS_NO_TILDE) #define IsNeedIdentd(x) ((x)->flags & CONF_FLAGS_NEED_IDENTD) #define IsConfExemptKline(x) ((x)->flags & CONF_FLAGS_EXEMPTKLINE) diff --git a/modules/m_dline.c b/modules/m_dline.c index 912091c..bb928ac 100644 --- a/modules/m_dline.c +++ b/modules/m_dline.c @@ -43,6 +43,7 @@ #include "parse.h" #include "modules.h" #include "bandbi.h" +#include "operhash.h" static int mo_dline(struct Client *, struct Client *, int, const char **); static int me_dline(struct Client *, struct Client *, int, const char **); @@ -289,6 +290,7 @@ apply_dline(struct Client *source_p, const char *dlhost, int tdline_time, char * aconf->created = rb_current_time(); aconf->host = rb_strdup(dlhost); aconf->passwd = rb_strdup(reason); + aconf->info.oper = operhash_add(get_oper_name(source_p)); /* Look for an oper reason */ if((oper_reason = strchr(reason, '|')) != NULL) diff --git a/modules/m_kline.c b/modules/m_kline.c index 18dbdca..b1cc350 100644 --- a/modules/m_kline.c +++ b/modules/m_kline.c @@ -44,6 +44,7 @@ #include "modules.h" #include "reject.h" #include "bandbi.h" +#include "operhash.h" static int mo_kline(struct Client *, struct Client *, int, const char **); static int ms_kline(struct Client *, struct Client *, int, const char **); @@ -174,6 +175,7 @@ mo_kline(struct Client *client_p, struct Client *source_p, int parc, const char aconf->user = rb_strdup(user); aconf->port = 0; aconf->passwd = rb_strdup(reason); + aconf->info.oper = operhash_add(get_oper_name(source_p)); /* Look for an oper reason */ if((oper_reason = strchr(reason, '|')) != NULL) @@ -276,6 +278,7 @@ handle_remote_kline(struct Client *source_p, int tkline_time, aconf->user = rb_strdup(user); aconf->host = rb_strdup(host); aconf->passwd = rb_strdup(reason); + aconf->info.oper = operhash_add(get_oper_name(source_p)); /* Look for an oper reason */ if((oper_reason = strchr(reason, '|')) != NULL) diff --git a/modules/m_resv.c b/modules/m_resv.c index 16db101..01b41b7 100644 --- a/modules/m_resv.c +++ b/modules/m_resv.c @@ -38,6 +38,7 @@ #include "hash.h" #include "logger.h" #include "bandbi.h" +#include "operhash.h" static int mo_resv(struct Client *, struct Client *, int, const char **); static int ms_resv(struct Client *, struct Client *, int, const char **); @@ -221,6 +222,7 @@ parse_resv(struct Client *source_p, const char *name, const char *reason, int te aconf->created = rb_current_time(); aconf->host = rb_strdup(name); aconf->passwd = rb_strdup(reason); + aconf->info.oper = operhash_add(get_oper_name(source_p)); add_to_resv_hash(aconf->host, aconf); resv_chan_forcepart(aconf->host, aconf->passwd, temp_time); @@ -285,6 +287,7 @@ parse_resv(struct Client *source_p, const char *name, const char *reason, int te aconf->created = rb_current_time(); aconf->host = rb_strdup(name); aconf->passwd = rb_strdup(reason); + aconf->info.oper = operhash_add(get_oper_name(source_p)); rb_dlinkAddAlloc(aconf, &resv_conf_list); if(temp_time > 0) diff --git a/modules/m_testline.c b/modules/m_testline.c index 7efc62c..05b7148 100644 --- a/modules/m_testline.c +++ b/modules/m_testline.c @@ -218,7 +218,7 @@ mo_testline(struct Client *client_p, struct Client *source_p, int parc, const ch if(aconf && aconf->status & CONF_CLIENT) { sendto_one_numeric(source_p, RPL_STATSILINE, form_str(RPL_STATSILINE), - aconf->name, EmptyString(aconf->spasswd) ? "" : aconf->spasswd, + aconf->info.name, EmptyString(aconf->spasswd) ? "" : aconf->spasswd, show_iline_prefix(source_p, aconf, aconf->user), aconf->host, aconf->port, aconf->className); return 0; diff --git a/modules/m_xline.c b/modules/m_xline.c index deb441f..556ad00 100644 --- a/modules/m_xline.c +++ b/modules/m_xline.c @@ -51,6 +51,7 @@ #include "s_newconf.h" #include "reject.h" #include "bandbi.h" +#include "operhash.h" static int mo_xline(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]); static int ms_xline(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]); @@ -280,6 +281,8 @@ apply_xline(struct Client *source_p, const char *name, const char *reason, int t aconf->passwd = rb_strdup(reason); collapse(aconf->host); + aconf->info.oper = operhash_add(get_oper_name(source_p)); + if(temp_time > 0) { aconf->hold = rb_current_time() + temp_time; diff --git a/src/Makefile.in b/src/Makefile.in index c24cd75..ab69afb 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -76,6 +76,7 @@ SRCS = \ monitor.c \ newconf.c \ numeric.c \ + operhash.c \ packet.c \ parse.c \ privilege.c \ diff --git a/src/bandbi.c b/src/bandbi.c index 4de4422..eda44b3 100644 --- a/src/bandbi.c +++ b/src/bandbi.c @@ -46,6 +46,7 @@ #include "send.h" #include "ircd.h" #include "msg.h" /* XXX: MAXPARA */ +#include "operhash.h" static char bandb_add_letter[LAST_BANDB_TYPE] = { 'K', 'D', 'X', 'R' @@ -170,8 +171,7 @@ bandb_handle_ban(char *parv[], int parc) aconf->user = rb_strdup(parv[para++]); aconf->host = rb_strdup(parv[para++]); - /* We do not have the 'oper' field yet. */ - para++; + aconf->info.oper = operhash_add(parv[para++]); switch (parv[0][0]) { diff --git a/src/hostmask.c b/src/hostmask.c index 806ecb8..1058df5 100644 --- a/src/hostmask.c +++ b/src/hostmask.c @@ -390,7 +390,7 @@ find_address_conf(const char *host, const char *sockhost, const char *user, /* if theres a spoof, check it against klines.. */ if(IsConfDoSpoofIp(iconf)) { - char *p = strchr(iconf->name, '@'); + char *p = strchr(iconf->info.name, '@'); /* note, we dont need to pass sockhost here, as its * guaranteed to not match by whats above.. --anfl @@ -398,11 +398,11 @@ find_address_conf(const char *host, const char *sockhost, const char *user, if(p) { *p = '\0'; - kconf = find_conf_by_address(p+1, NULL, NULL, ip, CONF_KILL, aftype, iconf->name, NULL); + kconf = find_conf_by_address(p+1, NULL, NULL, ip, CONF_KILL, aftype, iconf->info.name, NULL); *p = '@'; } else - kconf = find_conf_by_address(iconf->name, NULL, NULL, ip, CONF_KILL, aftype, vuser, NULL); + kconf = find_conf_by_address(iconf->info.name, NULL, NULL, ip, CONF_KILL, aftype, vuser, NULL); if(kconf) return kconf; diff --git a/src/newconf.c b/src/newconf.c index 7e186f2..18ea7fc 100644 --- a/src/newconf.c +++ b/src/newconf.c @@ -952,8 +952,8 @@ conf_end_auth(struct TopConf *tc) rb_dlink_node *ptr; rb_dlink_node *next_ptr; - if(EmptyString(yy_aconf->name)) - yy_aconf->name = rb_strdup("NOMATCH"); + if(EmptyString(yy_aconf->info.name)) + yy_aconf->info.name = rb_strdup("NOMATCH"); /* didnt even get one ->host? */ if(EmptyString(yy_aconf->host)) @@ -987,7 +987,7 @@ conf_end_auth(struct TopConf *tc) yy_tmp->spasswd = rb_strdup(yy_aconf->spasswd); /* this will always exist.. */ - yy_tmp->name = rb_strdup(yy_aconf->name); + yy_tmp->info.name = rb_strdup(yy_aconf->info.name); if(yy_aconf->className) yy_tmp->className = rb_strdup(yy_aconf->className); @@ -1138,8 +1138,8 @@ conf_set_auth_spoof(void *data) return; } - rb_free(yy_aconf->name); - yy_aconf->name = rb_strdup(data); + rb_free(yy_aconf->info.name); + yy_aconf->info.name = rb_strdup(data); yy_aconf->flags |= CONF_FLAGS_SPOOF_IP; } @@ -1155,8 +1155,8 @@ static void conf_set_auth_redir_serv(void *data) { yy_aconf->flags |= CONF_FLAGS_REDIR; - rb_free(yy_aconf->name); - yy_aconf->name = rb_strdup(data); + rb_free(yy_aconf->info.name); + yy_aconf->info.name = rb_strdup(data); } static void diff --git a/src/operhash.c b/src/operhash.c new file mode 100644 index 0000000..5e416d0 --- /dev/null +++ b/src/operhash.c @@ -0,0 +1,130 @@ +/* ircd-ratbox: an advanced Internet Relay Chat Daemon(ircd). + * operhash.c - Hashes nick!user@host{oper} + * + * Copyright (C) 2005 Lee Hardy + * Copyright (C) 2005 ircd-ratbox development team + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1.Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2.Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3.The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * $Id: operhash.c 26094 2008-09-19 15:33:46Z androsyn $ + */ +#include +#include "stdinc.h" +#include "match.h" +#include "hash.h" +#include "operhash.h" + +#define OPERHASH_MAX_BITS 7 +#define OPERHASH_MAX (1<data; + + if(!irccmp(ohash->name, name)) + { + ohash->refcount++; + return ohash->name; + } + } + + ohash = rb_malloc(sizeof(struct operhash_entry)); + ohash->refcount = 1; + ohash->name = rb_strdup(name); + + rb_dlinkAddAlloc(ohash, &operhash_table[hashv]); + + return ohash->name; +} + +const char * +operhash_find(const char *name) +{ + struct operhash_entry *ohash; + unsigned int hashv; + rb_dlink_node *ptr; + + if(EmptyString(name)) + return NULL; + + hashv = hash_opername(name); + + RB_DLINK_FOREACH(ptr, operhash_table[hashv].head) + { + ohash = ptr->data; + + if(!irccmp(ohash->name, name)) + return ohash->name; + } + + return NULL; +} + +void +operhash_delete(const char *name) +{ + struct operhash_entry *ohash; + unsigned int hashv; + rb_dlink_node *ptr; + + if(EmptyString(name)) + return; + + hashv = hash_opername(name); + + RB_DLINK_FOREACH(ptr, operhash_table[hashv].head) + { + ohash = ptr->data; + + if(irccmp(ohash->name, name)) + continue; + + ohash->refcount--; + + if(ohash->refcount == 0) + { + rb_free(ohash->name); + rb_free(ohash); + rb_dlinkDestroy(ptr, &operhash_table[hashv]); + return; + } + } +} diff --git a/src/s_conf.c b/src/s_conf.c index c3df6fd..56849bd 100644 --- a/src/s_conf.c +++ b/src/s_conf.c @@ -51,6 +51,7 @@ #include "privilege.h" #include "sslproc.h" #include "bandbi.h" +#include "operhash.h" struct config_server_hide ConfigServerHide; @@ -143,11 +144,15 @@ free_conf(struct ConfItem *aconf) rb_free(aconf->passwd); rb_free(aconf->spasswd); - rb_free(aconf->name); rb_free(aconf->className); rb_free(aconf->user); rb_free(aconf->host); + if(IsConfBan(aconf)) + operhash_delete(aconf->info.oper); + else + rb_free(aconf->info.name); + rb_bh_free(confitem_heap, aconf); } @@ -334,7 +339,7 @@ verify_access(struct Client *client_p, const char *username) if(aconf->flags & CONF_FLAGS_REDIR) { sendto_one_numeric(client_p, RPL_REDIR, form_str(RPL_REDIR), - aconf->name ? aconf->name : "", aconf->port); + aconf->info.name ? aconf->info.name : "", aconf->port); return (NOT_AUTHORISED); } @@ -351,24 +356,24 @@ verify_access(struct Client *client_p, const char *username) sendto_realops_snomask(SNO_GENERAL, L_ALL, "%s spoofing: %s as %s", client_p->name, - show_ip(NULL, client_p) ? client_p->host : aconf->name, - aconf->name); + show_ip(NULL, client_p) ? client_p->host : aconf->info.name, + aconf->info.name); } /* user@host spoof */ - if((p = strchr(aconf->name, '@')) != NULL) + if((p = strchr(aconf->info.name, '@')) != NULL) { char *host = p+1; *p = '\0'; - rb_strlcpy(client_p->username, aconf->name, + rb_strlcpy(client_p->username, aconf->info.name, sizeof(client_p->username)); rb_strlcpy(client_p->host, host, sizeof(client_p->host)); *p = '@'; } else - rb_strlcpy(client_p->host, aconf->name, sizeof(client_p->host)); + rb_strlcpy(client_p->host, aconf->info.name, sizeof(client_p->host)); } return (attach_iline(client_p, aconf)); } @@ -1115,7 +1120,7 @@ get_printable_conf(struct ConfItem *aconf, char **name, char **host, static char null[] = ""; static char zero[] = "default"; - *name = EmptyString(aconf->name) ? null : aconf->name; + *name = EmptyString(aconf->info.name) ? null : aconf->info.name; *host = EmptyString(aconf->host) ? null : aconf->host; *pass = EmptyString(aconf->passwd) ? null : aconf->passwd; *user = EmptyString(aconf->user) ? null : aconf->user; diff --git a/src/s_user.c b/src/s_user.c index c315565..7e2f11d 100644 --- a/src/s_user.c +++ b/src/s_user.c @@ -336,7 +336,7 @@ register_local_user(struct Client *client_p, struct Client *source_p, const char } /* dont replace username if its supposed to be spoofed --fl */ - if(!IsConfDoSpoofIp(aconf) || !strchr(aconf->name, '@')) + if(!IsConfDoSpoofIp(aconf) || !strchr(aconf->info.name, '@')) { p = username; From cf06f92b783219f7fa39ba9b145de2e5d69a9747 Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Mon, 1 Mar 2010 01:24:00 +0100 Subject: [PATCH 06/32] Make struct operhash_entry private. --- include/operhash.h | 6 ------ src/operhash.c | 6 ++++++ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/operhash.h b/include/operhash.h index 643abf9..c999b72 100644 --- a/include/operhash.h +++ b/include/operhash.h @@ -1,12 +1,6 @@ #ifndef INCLUDED_operhash_h #define INCLUDED_operhash_h -struct operhash_entry -{ - char *name; - int refcount; -}; - void init_operhash(void); const char *operhash_add(const char *name); const char *operhash_find(const char *name); diff --git a/src/operhash.c b/src/operhash.c index 5e416d0..ed6cda1 100644 --- a/src/operhash.c +++ b/src/operhash.c @@ -41,6 +41,12 @@ #define hash_opername(x) fnv_hash_upper((const unsigned char *)(x), OPERHASH_MAX_BITS) +struct operhash_entry +{ + char *name; + int refcount; +}; + static rb_dlink_list operhash_table[OPERHASH_MAX]; const char * From 8a1d7222f41a351843a9118579012eef1e19c3d3 Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Wed, 3 Mar 2010 22:58:16 +0100 Subject: [PATCH 07/32] bandb: Group writes in transactions to reduce load on heavy kline activity. When a ban is added or removed, open a transaction and close it after 3 seconds; any bans in the 3 seconds will not trigger another transaction (= 4 fsyncs with sqlite). The transaction is also committed if ircd closes the connection, but not if bandb itself is terminated with a signal. --- bandb/bandb.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/bandb/bandb.c b/bandb/bandb.c index cce310c..33166b1 100644 --- a/bandb/bandb.c +++ b/bandb/bandb.c @@ -38,6 +38,8 @@ #define MAXPARA 10 +#define COMMIT_INTERVAL 3 /* seconds */ + typedef enum { BANDB_KLINE, @@ -57,9 +59,17 @@ static const char *bandb_table[LAST_BANDB_TYPE] = { static rb_helper *bandb_helper; +static int in_transaction; static void check_schema(void); +static void +bandb_commit(void *unused) +{ + rsdb_transaction(RSDB_TRANS_END); + in_transaction = 0; +} + static void parse_ban(bandb_type type, char *parv[], int parc) { @@ -89,6 +99,14 @@ parse_ban(bandb_type type, char *parv[], int parc) perm = parv[para++]; reason = parv[para++]; + if(!in_transaction) + { + rsdb_transaction(RSDB_TRANS_START); + in_transaction = 1; + rb_event_addonce("bandb_commit", bandb_commit, NULL, + COMMIT_INTERVAL); + } + rsdb_exec(NULL, "INSERT INTO %s (mask1, mask2, oper, time, perm, reason) VALUES('%Q', '%Q', '%Q', %s, %s, '%Q')", bandb_table[type], mask1, mask2 ? mask2 : "", oper, curtime, perm, reason); @@ -113,6 +131,14 @@ parse_unban(bandb_type type, char *parv[], int parc) if(type == BANDB_KLINE) mask2 = parv[2]; + if(!in_transaction) + { + rsdb_transaction(RSDB_TRANS_START); + in_transaction = 1; + rb_event_addonce("bandb_commit", bandb_commit, NULL, + COMMIT_INTERVAL); + } + rsdb_exec(NULL, "DELETE FROM %s WHERE mask1='%Q' AND mask2='%Q'", bandb_table[type], mask1, mask2 ? mask2 : ""); } @@ -215,6 +241,8 @@ parse_request(rb_helper *helper) static void error_cb(rb_helper *helper) { + if(in_transaction) + rsdb_transaction(RSDB_TRANS_END); exit(1); } From ebae0e200e23a710418700daff84d3545a70609c Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Wed, 3 Mar 2010 23:36:28 +0100 Subject: [PATCH 08/32] ConfItem.next is not used, remove it. --- include/s_conf.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/s_conf.h b/include/s_conf.h index a5ff080..5c27d87 100644 --- a/include/s_conf.h +++ b/include/s_conf.h @@ -56,7 +56,6 @@ extern char conf_line_in[256]; struct ConfItem { - struct ConfItem *next; /* list node pointer */ unsigned int status; /* If CONF_ILLEGAL, delete when no clients */ unsigned int flags; int clients; /* Number of *LOCAL* clients using this */ From 12894c8888675e4627d0e16b850e73648b5f3dce Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Thu, 4 Mar 2010 00:21:22 +0100 Subject: [PATCH 09/32] Add code to expire "propagated" bans. The data structure is very simple: a dlink list of all propagated bans. --- include/s_conf.h | 5 +++ src/s_conf.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++ src/s_newconf.c | 7 ++++ 3 files changed, 98 insertions(+) diff --git a/include/s_conf.h b/include/s_conf.h index 5c27d87..762dac1 100644 --- a/include/s_conf.h +++ b/include/s_conf.h @@ -73,6 +73,7 @@ struct ConfItem int port; time_t hold; /* Hold action until this time (calendar time) */ time_t created; /* Creation time (for klines etc) */ + time_t lifetime; /* Propagated lines: remember until this time */ char *className; /* Name of class */ struct Class *c_class; /* Class of connection */ rb_patricia_node_t *pnode; /* Our patricia node */ @@ -327,6 +328,8 @@ extern struct admin_info AdminInfo; /* defined in ircd.c */ extern rb_dlink_list service_list; +extern rb_dlink_list prop_bans; + typedef enum temp_list { TEMP_MIN, @@ -344,6 +347,8 @@ extern void init_s_conf(void); extern struct ConfItem *make_conf(void); extern void free_conf(struct ConfItem *); +extern void deactivate_conf(struct ConfItem *, rb_dlink_node *); + extern void read_conf_files(int cold); extern int attach_conf(struct Client *, struct ConfItem *); diff --git a/src/s_conf.c b/src/s_conf.c index 56849bd..6ccdeb4 100644 --- a/src/s_conf.c +++ b/src/s_conf.c @@ -64,6 +64,8 @@ extern char linebuf[]; static rb_bh *confitem_heap = NULL; +rb_dlink_list prop_bans; + rb_dlink_list temp_klines[LAST_TEMP_TYPE]; rb_dlink_list temp_dlines[LAST_TEMP_TYPE]; rb_dlink_list service_list; @@ -74,6 +76,7 @@ static void validate_conf(void); static void read_conf(FILE *); static void clear_out_old_conf(void); +static void expire_prop_bans(void *list); static void expire_temp_kd(void *list); static void reorganise_temp_kd(void *list); @@ -88,6 +91,8 @@ init_s_conf(void) { confitem_heap = rb_bh_create(sizeof(struct ConfItem), CONFITEM_HEAP_SIZE, "confitem_heap"); + rb_event_addish("expire_prop_bans", expire_prop_bans, &prop_bans, 60); + rb_event_addish("expire_temp_klines", expire_temp_kd, &temp_klines[TEMP_MIN], 60); rb_event_addish("expire_temp_dlines", expire_temp_kd, &temp_dlines[TEMP_MIN], 60); @@ -1002,6 +1007,87 @@ add_temp_dline(struct ConfItem *aconf) add_conf_by_address(aconf->host, CONF_DLINE, aconf->user, NULL, aconf); } +void +deactivate_conf(struct ConfItem *aconf, rb_dlink_node *ptr) +{ + int i; + + s_assert(ptr->data == aconf); + + switch (aconf->status) + { + case CONF_KILL: + if (aconf->lifetime == 0 && + aconf->flags & CONF_FLAGS_TEMPORARY) + for (i = 0; i < LAST_TEMP_TYPE; i++) + rb_dlinkFindDestroy(aconf, &temp_klines[i]); + /* Make sure delete_one_address_conf() does not + * free the aconf. + */ + aconf->clients++; + delete_one_address_conf(aconf->host, aconf); + aconf->clients--; + break; + case CONF_DLINE: + if (aconf->lifetime == 0 && + aconf->flags & CONF_FLAGS_TEMPORARY) + for (i = 0; i < LAST_TEMP_TYPE; i++) + rb_dlinkFindDestroy(aconf, &temp_dlines[i]); + aconf->clients++; + delete_one_address_conf(aconf->host, aconf); + aconf->clients--; + break; + case CONF_XLINE: + rb_dlinkFindDestroy(aconf, &xline_conf_list); + break; + case CONF_RESV_NICK: + rb_dlinkFindDestroy(aconf, &resv_conf_list); + break; + case CONF_RESV_CHANNEL: + del_from_resv_hash(aconf->host, aconf); + break; + } + if (aconf->lifetime != 0 && rb_current_time() < aconf->lifetime) + aconf->status |= CONF_ILLEGAL; + else + { + if (aconf->lifetime != 0) + rb_dlinkDestroy(ptr, &prop_bans); + free_conf(aconf); + } +} + +static void +expire_prop_bans(void *list) +{ + rb_dlink_node *ptr; + rb_dlink_node *next_ptr; + struct ConfItem *aconf; + + RB_DLINK_FOREACH_SAFE(ptr, next_ptr, ((rb_dlink_list *) list)->head) + { + aconf = ptr->data; + + if(aconf->lifetime <= rb_current_time() || + (aconf->hold <= rb_current_time() && + !(aconf->status & CONF_ILLEGAL))) + { + /* Alert opers that a TKline expired - Hwy */ + /* XXX show what type of ban it is */ + if(ConfigFileEntry.tkline_expire_notices && + !(aconf->status & CONF_ILLEGAL)) + sendto_realops_snomask(SNO_GENERAL, L_ALL, + "Propagated ban for [%s%s%s] expired", + aconf->user ? aconf->user : "", + aconf->user ? "@" : "", + aconf->host ? aconf->host : "*"); + + /* will destroy or mark illegal */ + deactivate_conf(aconf, ptr); + } + } +} + /* expire_tkline() * * inputs - list pointer diff --git a/src/s_newconf.c b/src/s_newconf.c index 592b410..36e94a5 100644 --- a/src/s_newconf.c +++ b/src/s_newconf.c @@ -651,6 +651,7 @@ valid_temp_time(const char *p) return(result * 60); } +/* Propagated bans are expired elsewhere. */ static void expire_temp_rxlines(void *unused) { @@ -663,6 +664,8 @@ expire_temp_rxlines(void *unused) { aconf = ptr->data; + if(aconf->lifetime != 0) + continue; if(aconf->hold && aconf->hold <= rb_current_time()) { if(ConfigFileEntry.tkline_expire_notices) @@ -680,6 +683,8 @@ expire_temp_rxlines(void *unused) { aconf = ptr->data; + if(aconf->lifetime != 0) + continue; if(aconf->hold && aconf->hold <= rb_current_time()) { if(ConfigFileEntry.tkline_expire_notices) @@ -695,6 +700,8 @@ expire_temp_rxlines(void *unused) { aconf = ptr->data; + if(aconf->lifetime != 0) + continue; if(aconf->hold && aconf->hold <= rb_current_time()) { if(ConfigFileEntry.tkline_expire_notices) From a491246f8f15e4f12d279095813d059e10099a39 Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Fri, 5 Mar 2010 00:37:56 +0100 Subject: [PATCH 10/32] Skip propagated bans in rehash txlines/tresvs. --- modules/m_rehash.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/m_rehash.c b/modules/m_rehash.c index 40cc7de..8557f8c 100644 --- a/modules/m_rehash.c +++ b/modules/m_rehash.c @@ -174,7 +174,7 @@ rehash_txlines(struct Client *source_p) { aconf = ptr->data; - if(!aconf->hold) + if(!aconf->hold || aconf->lifetime) continue; free_conf(aconf); @@ -199,7 +199,7 @@ rehash_tresvs(struct Client *source_p) { aconf = ptr->data; - if(!aconf->hold) + if(!aconf->hold || aconf->lifetime) continue; free_conf(aconf); @@ -211,7 +211,7 @@ rehash_tresvs(struct Client *source_p) { aconf = ptr->data; - if(!aconf->hold) + if(!aconf->hold || aconf->lifetime) continue; free_conf(aconf); From dce31e272391c727bc3caa29ca6a6eb445a00fcb Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Fri, 5 Mar 2010 17:28:47 +0100 Subject: [PATCH 11/32] Fix --disable-balloc. libratbox r26769 --- libratbox/src/balloc.c | 13 ++++++++----- libratbox/src/linebuf.c | 2 -- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/libratbox/src/balloc.c b/libratbox/src/balloc.c index c827614..a147feb 100644 --- a/libratbox/src/balloc.c +++ b/libratbox/src/balloc.c @@ -492,11 +492,14 @@ rb_bh_usage(rb_bh *bh, size_t *bused, size_t *bfree, size_t *bmemusage, const ch if(desc != NULL) *desc = bh->desc; #else - static char *noballoc = "no blockheap"; - *bused = 0; - *bfree = 0; - *bmemusage = 0; - *desc = noballoc; + if(bused != NULL) + *bused = 0; + if(bfree != NULL) + *bfree = 0; + if(bmemusage != NULL) + *bmemusage = 0; + if(desc != NULL) + *desc = "no blockheap"; #endif } diff --git a/libratbox/src/linebuf.c b/libratbox/src/linebuf.c index 5e7fbb4..b3d2bb9 100644 --- a/libratbox/src/linebuf.c +++ b/libratbox/src/linebuf.c @@ -28,9 +28,7 @@ #include #include -#ifndef NOBALLOC static rb_bh *rb_linebuf_heap; -#endif static int bufline_count = 0; From 90072e8be6b3674ff6bf017fed9517740363e940 Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Fri, 5 Mar 2010 18:28:59 +0100 Subject: [PATCH 12/32] kline: Fix oper reasons. --- modules/m_kline.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/m_kline.c b/modules/m_kline.c index b1cc350..2056e4d 100644 --- a/modules/m_kline.c +++ b/modules/m_kline.c @@ -174,7 +174,6 @@ mo_kline(struct Client *client_p, struct Client *source_p, int parc, const char aconf->host = rb_strdup(host); aconf->user = rb_strdup(user); aconf->port = 0; - aconf->passwd = rb_strdup(reason); aconf->info.oper = operhash_add(get_oper_name(source_p)); /* Look for an oper reason */ @@ -186,6 +185,7 @@ mo_kline(struct Client *client_p, struct Client *source_p, int parc, const char if(!EmptyString(oper_reason)) aconf->spasswd = rb_strdup(oper_reason); } + aconf->passwd = rb_strdup(reason); if(tkline_time > 0) apply_tkline(source_p, aconf, reason, oper_reason, tkline_time); @@ -277,7 +277,6 @@ handle_remote_kline(struct Client *source_p, int tkline_time, aconf->created = rb_current_time(); aconf->user = rb_strdup(user); aconf->host = rb_strdup(host); - aconf->passwd = rb_strdup(reason); aconf->info.oper = operhash_add(get_oper_name(source_p)); /* Look for an oper reason */ @@ -289,6 +288,7 @@ handle_remote_kline(struct Client *source_p, int tkline_time, if(!EmptyString(oper_reason)) aconf->spasswd = rb_strdup(oper_reason); } + aconf->passwd = rb_strdup(reason); if(tkline_time > 0) apply_tkline(source_p, aconf, reason, oper_reason, tkline_time); From 65b8e0029ece152f56ea31919957ba1563e20eb4 Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Fri, 5 Mar 2010 18:36:44 +0100 Subject: [PATCH 13/32] Add propagated klines. A KLINE command without the ON clause now sets a propagated ("global") ban. KLINE commands with the ON clause work as before. Propagated klines can only be removed with an UNKLINE command without the ON clause, and this removes them everywhere. In fact, they remain in a deactivated state until the latest expiry ever used for the mask has passed. Propagated klines are part of the netburst using a new BAN message and capab. If such a burst has an effect, both the server name and the original oper are shown in the server notice. No checks whatsoever are done on bursted klines at this time. The system should be extended to XLINE and RESV later. There is currently no way to list propagated klines, but TESTLINE works normally. --- include/s_conf.h | 2 + include/s_serv.h | 4 +- modules/Makefile.in | 1 + modules/core/m_ban.c | 241 +++++++++++++++++++++++++++++++++++++++++++ modules/m_kline.c | 143 ++++++++++++++++++++++++- src/modules.c | 1 + src/s_conf.c | 19 ++++ src/s_serv.c | 65 ++++++++++++ 8 files changed, 471 insertions(+), 5 deletions(-) create mode 100644 modules/core/m_ban.c diff --git a/include/s_conf.h b/include/s_conf.h index 762dac1..6573e7b 100644 --- a/include/s_conf.h +++ b/include/s_conf.h @@ -97,6 +97,7 @@ struct ConfItem /* Generic flags... */ #define CONF_FLAGS_TEMPORARY 0x00800000 #define CONF_FLAGS_NEED_SSL 0x00000002 +#define CONF_FLAGS_MYOPER 0x00080000 /* need to rewrite info.oper on burst */ /* auth{} flags... */ #define CONF_FLAGS_NO_TILDE 0x00000004 #define CONF_FLAGS_NEED_IDENTD 0x00000008 @@ -347,6 +348,7 @@ extern void init_s_conf(void); extern struct ConfItem *make_conf(void); extern void free_conf(struct ConfItem *); +extern rb_dlink_node *find_prop_ban(unsigned int status, const char *user, const char *host); extern void deactivate_conf(struct ConfItem *, rb_dlink_node *); extern void read_conf_files(int cold); diff --git a/include/s_serv.h b/include/s_serv.h index c52c78d..73327c7 100644 --- a/include/s_serv.h +++ b/include/s_serv.h @@ -72,12 +72,14 @@ struct Capability #define CAP_SAVE 0x40000 /* supports SAVE (nick collision FNC) */ #define CAP_EUID 0x80000 /* supports EUID (ext UID + nonencap CHGHOST) */ #define CAP_EOPMOD 0x100000 /* supports EOPMOD (ext +z + ext topic) */ +#define CAP_BAN 0x200000 /* supports propagated bans */ #define CAP_MASK (CAP_QS | CAP_EX | CAP_CHW | \ CAP_IE | CAP_KLN | CAP_SERVICE |\ CAP_CLUSTER | CAP_ENCAP | \ CAP_ZIP | CAP_KNOCK | CAP_UNKLN | \ - CAP_RSFNC | CAP_SAVE | CAP_EUID | CAP_EOPMOD) + CAP_RSFNC | CAP_SAVE | CAP_EUID | CAP_EOPMOD | \ + CAP_BAN) #ifdef HAVE_LIBZ #define CAP_ZIP_SUPPORTED CAP_ZIP diff --git a/modules/Makefile.in b/modules/Makefile.in index 6c80e21..ad1aace 100644 --- a/modules/Makefile.in +++ b/modules/Makefile.in @@ -36,6 +36,7 @@ INCLUDES = -I../include -I../libratbox/include $(SSL_INCLUDES) CPPFLAGS = ${INCLUDES} @CPPFLAGS@ CORE_SRCS = \ + core/m_ban.c \ core/m_die.c \ core/m_error.c \ core/m_join.c \ diff --git a/modules/core/m_ban.c b/modules/core/m_ban.c new file mode 100644 index 0000000..fb19c57 --- /dev/null +++ b/modules/core/m_ban.c @@ -0,0 +1,241 @@ +/* + * charybdis: An advanced ircd. + * m_ban.c: Propagates network bans across servers. + * + * Copyright (C) 2010 Jilles Tjoelker + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1.Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2.Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "stdinc.h" +#include "send.h" +#include "client.h" +#include "common.h" +#include "config.h" +#include "ircd.h" +#include "match.h" +#include "s_conf.h" +#include "msg.h" +#include "modules.h" +#include "hash.h" +#include "s_serv.h" +#include "operhash.h" +#include "reject.h" +#include "hostmask.h" + +static int ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]); + +struct Message ban_msgtab = { + "BAN", 0, 0, 0, MFLG_SLOW, + {mg_unreg, mg_ignore, {ms_ban, 10}, {ms_ban, 10}, mg_ignore, mg_ignore} +}; + +mapi_clist_av1 ban_clist[] = { &ban_msgtab, NULL }; +DECLARE_MODULE_AV1(ban, NULL, NULL, ban_clist, NULL, NULL, "$Revision: 1349 $"); + +/* ms_ban() + * + * parv[1] - +/- + * parv[2] - type + * parv[3] - username mask or * + * parv[4] - hostname mask + * parv[5] - creation TS + * parv[6] - duration (relative to creation) + * parv[7] - lifetime (relative to creation) + * parv[8] - oper or * + * parv[9] - reason (possibly with |operreason) + */ +static int +ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) +{ + rb_dlink_node *ptr; + struct ConfItem *aconf; + unsigned int ntype; + const char *oper, *stype; + time_t created, hold, lifetime; + char *p; + int act; + + if (strcmp(parv[1], "+") && strcmp(parv[1], "-")) + { + sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, + "Unknown BAN operation %s from %s", + parv[1], source_p->name); + return 0; + } + if (strlen(parv[2]) != 1) + { + sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, + "Unknown BAN type %s from %s", + parv[2], source_p->name); + return 0; + } + switch (parv[2][0]) + { + case 'K': + ntype = CONF_KILL; + stype = "K-Line"; + break; + default: + sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, + "Unknown BAN type %s from %s", + parv[2], source_p->name); + return 0; + } + created = atol(parv[5]); + hold = created + atoi(parv[6]); + lifetime = created + atoi(parv[7]); + if (!strcmp(parv[8], "*")) + oper = IsServer(source_p) ? source_p->name : get_oper_name(source_p); + else + oper = parv[8]; + ptr = find_prop_ban(ntype, parv[3], parv[4]); + if (ptr != NULL) + { + aconf = ptr->data; + if (aconf->created >= created) + { + if (IsPerson(source_p)) + sendto_one_notice(source_p, + ":Your %s [%s%s%s] has been superseded", + stype, + aconf->user ? aconf->user : "", + aconf->user ? "@" : "", + aconf->host); + return 0; + } + act = !(aconf->status & CONF_ILLEGAL) || !strcmp(parv[1], "+"); + if (lifetime > aconf->lifetime) + aconf->lifetime = lifetime; + /* already expired, hmm */ + if (aconf->lifetime <= rb_current_time()) + return 0; + deactivate_conf(aconf, ptr); + rb_free(aconf->user); + aconf->user = NULL; + rb_free(aconf->host); + aconf->host = NULL; + operhash_delete(aconf->info.oper); + aconf->info.oper = NULL; + rb_free(aconf->passwd); + aconf->passwd = NULL; + rb_free(aconf->spasswd); + aconf->spasswd = NULL; + } + else + { + aconf = make_conf(); + aconf->status = CONF_ILLEGAL | ntype; + aconf->lifetime = lifetime; + rb_dlinkAddAlloc(aconf, &prop_bans); + act = !strcmp(parv[1], "+"); + } + aconf->flags &= ~CONF_FLAGS_MYOPER; + aconf->flags |= CONF_FLAGS_TEMPORARY; + aconf->user = ntype == CONF_KILL ? rb_strdup(parv[3]) : NULL; + aconf->host = rb_strdup(parv[4]); + aconf->info.oper = operhash_add(oper); + aconf->created = created; + aconf->hold = hold; + p = strchr(parv[parc - 1], '|'); + if (p == NULL) + aconf->passwd = rb_strdup(parv[parc - 1]); + else + { + aconf->passwd = rb_strndup(parv[parc - 1], p - parv[parc - 1] + 1); + aconf->spasswd = rb_strdup(p + 1); + } + if (!strcmp(parv[1], "+")) + { + /* Keep the notices in sync with modules/m_kline.c etc. */ + sendto_realops_snomask(SNO_GENERAL, L_ALL, + "%s added global %d min. %s%s%s for [%s%s%s] [%s]", + IsServer(source_p) ? source_p->name : get_oper_name(source_p), + (hold - rb_current_time()) / 60, + stype, + strcmp(parv[8], "*") ? " from " : "", + strcmp(parv[8], "*") ? parv[8] : "", + aconf->user ? aconf->user : "", + aconf->user ? "@" : "", + aconf->host, + parv[parc - 1]); + aconf->status &= ~CONF_ILLEGAL; + ilog(L_KLINE, "%s %s %d %s %s %s", parv[2], + IsServer(source_p) ? source_p->name : get_oper_name(source_p), + (hold - rb_current_time()) / 60, + aconf->user, aconf->host, + parv[parc - 1]); + } + else if (act) + { + sendto_realops_snomask(SNO_GENERAL, L_ALL, + "%s has removed the global %s for: [%s%s%s]%s%s", + IsServer(source_p) ? source_p->name : get_oper_name(source_p), + stype, + aconf->user ? aconf->user : "", + aconf->user ? "@" : "", + aconf->host, + strcmp(parv[8], "*") ? " on behalf of " : "", + strcmp(parv[8], "*") ? parv[8] : ""); + ilog(L_KLINE, "U%s %s %s %s", parv[2], + IsServer(source_p) ? source_p->name : get_oper_name(source_p), + aconf->user, aconf->host); + } + switch (ntype) + { + case CONF_KILL: + if (aconf->status & CONF_ILLEGAL) + remove_reject_mask(aconf->user, aconf->host); + else + { + add_conf_by_address(aconf->host, CONF_KILL, aconf->user, NULL, aconf); + if(ConfigFileEntry.kline_delay || + (IsServer(source_p) && + !HasSentEob(source_p))) + { + if(kline_queued == 0) + { + rb_event_addonce("check_klines", check_klines_event, NULL, + ConfigFileEntry.kline_delay); + kline_queued = 1; + } + } + else + check_klines(); + } + break; + } + sendto_server(NULL, NULL, CAP_BAN|CAP_TS6, NOCAPS, + ":%s BAN %s %s %s %s %s %s %s %s :%s", + source_p->id, + parv[1], + parv[2], + parv[3], + parv[4], + parv[5], + parv[6], + parv[7], + parv[8], + parv[parc - 1]); + return 0; +} diff --git a/modules/m_kline.c b/modules/m_kline.c index 2056e4d..4ba0561 100644 --- a/modules/m_kline.c +++ b/modules/m_kline.c @@ -79,11 +79,14 @@ static void apply_kline(struct Client *source_p, struct ConfItem *aconf, const char *reason, const char *oper_reason); static void apply_tkline(struct Client *source_p, struct ConfItem *aconf, const char *, const char *, int); +static void apply_prop_kline(struct Client *source_p, struct ConfItem *aconf, + const char *, const char *, int); static int already_placed_kline(struct Client *, const char *, const char *, int); static void handle_remote_unkline(struct Client *source_p, const char *user, const char *host); static void remove_permkline_match(struct Client *, struct ConfItem *); static int remove_temp_kline(struct Client *, struct ConfItem *); +static void remove_prop_kline(struct Client *, struct ConfItem *); /* mo_kline() * @@ -105,6 +108,7 @@ mo_kline(struct Client *client_p, struct Client *source_p, int parc, const char struct ConfItem *aconf; int tkline_time = 0; int loc = 1; + int propagated = 1; if(!IsOperK(source_p)) { @@ -153,9 +157,12 @@ mo_kline(struct Client *client_p, struct Client *source_p, int parc, const char /* If we are sending it somewhere that doesnt include us, stop */ if(!match(target_server, me.name)) return 0; + + /* Set as local-only. */ + propagated = 0; } /* if we have cluster servers, send it to them.. */ - else if(rb_dlink_list_length(&cluster_conf_list) > 0) + else if(!propagated && rb_dlink_list_length(&cluster_conf_list) > 0) cluster_generic(source_p, "KLINE", (tkline_time > 0) ? SHARED_TKLINE : SHARED_PKLINE, CAP_KLN, "%lu %s %s :%s", tkline_time, user, host, reason); @@ -164,6 +171,12 @@ mo_kline(struct Client *client_p, struct Client *source_p, int parc, const char !valid_wild_card(source_p, user, host) || !valid_comment(source_p, reason)) return 0; + if(propagated && tkline_time == 0) + { + sendto_one_notice(source_p, ":Cannot set a permanent global ban"); + return 0; + } + if(already_placed_kline(source_p, user, host, tkline_time)) return 0; @@ -187,7 +200,9 @@ mo_kline(struct Client *client_p, struct Client *source_p, int parc, const char } aconf->passwd = rb_strdup(reason); - if(tkline_time > 0) + if(propagated) + apply_prop_kline(source_p, aconf, reason, oper_reason, tkline_time); + else if(tkline_time > 0) apply_tkline(source_p, aconf, reason, oper_reason, tkline_time); else apply_kline(source_p, aconf, reason, oper_reason); @@ -324,6 +339,7 @@ mo_unkline(struct Client *client_p, struct Client *source_p, int parc, const cha char splat[] = "*"; char *h = LOCAL_COPY(parv[1]); struct ConfItem *aconf; + int propagated = 1; if(!IsOperUnkline(source_p)) { @@ -375,17 +391,32 @@ mo_unkline(struct Client *client_p, struct Client *source_p, int parc, const cha if(match(parv[3], me.name) == 0) return 0; + + propagated = 0; } - else if(rb_dlink_list_length(&cluster_conf_list) > 0) + + aconf = find_exact_conf_by_address(host, CONF_KILL, user); + + /* No clustering for removing a propagated kline */ + if(propagated && (aconf == NULL || !aconf->lifetime) && + rb_dlink_list_length(&cluster_conf_list) > 0) cluster_generic(source_p, "UNKLINE", SHARED_UNKLINE, CAP_UNKLN, "%s %s", user, host); - aconf = find_exact_conf_by_address(host, CONF_KILL, user); if(aconf == NULL) { sendto_one_notice(source_p, ":No K-Line for %s@%s", user, host); return 0; } + + if(aconf->lifetime) + { + if(propagated) + remove_prop_kline(source_p, aconf); + else + sendto_one_notice(source_p, ":Cannot remove global K-Line %s@%s on specific servers", user, host); + return 0; + } if(remove_temp_kline(source_p, aconf)) return 0; @@ -444,6 +475,11 @@ handle_remote_unkline(struct Client *source_p, const char *user, const char *hos sendto_one_notice(source_p, ":No K-Line for %s@%s", user, host); return; } + if(aconf->lifetime) + { + sendto_one_notice(source_p, ":Cannot remove global K-Line %s@%s on specific servers", user, host); + return; + } if(remove_temp_kline(source_p, aconf)) return; @@ -527,6 +563,70 @@ apply_tkline(struct Client *source_p, struct ConfItem *aconf, tkline_time / 60, aconf->user, aconf->host); } +static void +apply_prop_kline(struct Client *source_p, struct ConfItem *aconf, + const char *reason, const char *oper_reason, int tkline_time) +{ + rb_dlink_node *ptr; + struct ConfItem *oldconf; + + aconf->flags |= CONF_FLAGS_MYOPER | CONF_FLAGS_TEMPORARY; + aconf->hold = rb_current_time() + tkline_time; + aconf->lifetime = aconf->hold; + + ptr = find_prop_ban(aconf->status, aconf->user, aconf->host); + if(ptr != NULL) + { + oldconf = ptr->data; + /* Remember at least as long as the old one. */ + if(oldconf->lifetime > aconf->lifetime) + aconf->lifetime = oldconf->lifetime; + /* Force creation time to increase. */ + if(oldconf->created >= aconf->created) + aconf->created = oldconf->created + 1; + /* Tell deactivate_conf() to destroy it. */ + oldconf->lifetime = rb_current_time(); + deactivate_conf(oldconf, ptr); + } + + rb_dlinkAddAlloc(aconf, &prop_bans); + add_conf_by_address(aconf->host, CONF_KILL, aconf->user, NULL, aconf); + + /* no oper reason.. */ + if(EmptyString(oper_reason)) + { + sendto_realops_snomask(SNO_GENERAL, L_ALL, + "%s added global %d min. K-Line for [%s@%s] [%s]", + get_oper_name(source_p), tkline_time / 60, + aconf->user, aconf->host, reason); + ilog(L_KLINE, "K %s %d %s %s %s", + get_oper_name(source_p), tkline_time / 60, aconf->user, aconf->host, reason); + } + else + { + sendto_realops_snomask(SNO_GENERAL, L_ALL, + "%s added global %d min. K-Line for [%s@%s] [%s|%s]", + get_oper_name(source_p), tkline_time / 60, + aconf->user, aconf->host, reason, oper_reason); + ilog(L_KLINE, "K %s %d %s %s %s|%s", + get_oper_name(source_p), tkline_time / 60, + aconf->user, aconf->host, reason, oper_reason); + } + + sendto_one_notice(source_p, ":Added global %d min. K-Line [%s@%s]", + tkline_time / 60, aconf->user, aconf->host); + + sendto_server(NULL, NULL, CAP_BAN|CAP_TS6, NOCAPS, + ":%s BAN + K %s %s %lu %d %d * :%s%s%s", + source_p->id, aconf->user, aconf->host, + (unsigned long)aconf->created, + (int)(aconf->hold - aconf->created), + (int)(aconf->lifetime - aconf->created), + reason, + oper_reason ? "|" : "", + oper_reason ? oper_reason : ""); +} + /* find_user_host() * * inputs - client placing kline, user@host, user buffer, host buffer @@ -799,3 +899,38 @@ remove_temp_kline(struct Client *source_p, struct ConfItem *aconf) return NO; } + +static void +remove_prop_kline(struct Client *source_p, struct ConfItem *aconf) +{ + rb_dlink_node *ptr; + + ptr = rb_dlinkFind(aconf, &prop_bans); + if (!ptr) + return; + sendto_one_notice(source_p, + ":Un-klined [%s@%s] from global k-lines", + aconf->user, aconf->host); + sendto_realops_snomask(SNO_GENERAL, L_ALL, + "%s has removed the global K-Line for: [%s@%s]", + get_oper_name(source_p), aconf->user, + aconf->host); + + ilog(L_KLINE, "UK %s %s %s", + get_oper_name(source_p), aconf->user, aconf->host); + if(aconf->created < rb_current_time()) + aconf->created = rb_current_time(); + else + aconf->created++; + operhash_delete(aconf->info.oper); + aconf->info.oper = operhash_add(get_oper_name(source_p)); + aconf->flags |= CONF_FLAGS_MYOPER | CONF_FLAGS_TEMPORARY; + sendto_server(NULL, NULL, CAP_BAN|CAP_TS6, NOCAPS, + ":%s BAN - K %s %s %lu %d %d * :*", + source_p->id, aconf->user, aconf->host, + (unsigned long)aconf->created, + 0, + (int)(aconf->lifetime - aconf->created)); + remove_reject_mask(aconf->user, aconf->host); + deactivate_conf(aconf, ptr); +} diff --git a/src/modules.c b/src/modules.c index 43a2f51..25d8cc7 100644 --- a/src/modules.c +++ b/src/modules.c @@ -58,6 +58,7 @@ struct module **modlist = NULL; static const char *core_module_table[] = { + "m_ban", "m_die", "m_error", "m_join", diff --git a/src/s_conf.c b/src/s_conf.c index 6ccdeb4..55a9728 100644 --- a/src/s_conf.c +++ b/src/s_conf.c @@ -1007,6 +1007,25 @@ add_temp_dline(struct ConfItem *aconf) add_conf_by_address(aconf->host, CONF_DLINE, aconf->user, NULL, aconf); } +rb_dlink_node * +find_prop_ban(unsigned int status, const char *user, const char *host) +{ + rb_dlink_node *ptr; + struct ConfItem *aconf; + + RB_DLINK_FOREACH(ptr, prop_bans.head) + { + aconf = ptr->data; + + if((aconf->status & ~CONF_ILLEGAL) == status && + (!user || !aconf->user || + !irccmp(aconf->user, user)) && + !irccmp(aconf->host, host)) + return ptr; + } + return NULL; +} + void deactivate_conf(struct ConfItem *aconf, rb_dlink_node *ptr) { diff --git a/src/s_serv.c b/src/s_serv.c index 315e18a..e71b1f3 100644 --- a/src/s_serv.c +++ b/src/s_serv.c @@ -89,6 +89,7 @@ struct Capability captab[] = { { "SAVE", CAP_SAVE }, { "EUID", CAP_EUID }, { "EOPMOD", CAP_EOPMOD }, + { "BAN", CAP_BAN }, {0, 0} }; @@ -392,6 +393,67 @@ send_capabilities(struct Client *client_p, int cap_can_send) sendto_one(client_p, "CAPAB :%s", msgbuf); } +static void +burst_ban(struct Client *client_p) +{ + rb_dlink_node *ptr; + struct ConfItem *aconf; + const char *type, *oper; + /* +5 for !,@,{,} and null */ + char operbuf[NICKLEN + USERLEN + HOSTLEN + HOSTLEN + 5]; + char *p; + size_t melen; + + melen = strlen(me.name); + RB_DLINK_FOREACH(ptr, prop_bans.head) + { + aconf = ptr->data; + + /* Skip expired stuff. */ + if(aconf->lifetime < rb_current_time()) + continue; + switch(aconf->status & ~CONF_ILLEGAL) + { + case CONF_KILL: type = "K"; break; + case CONF_DLINE: type = "D"; break; + case CONF_XLINE: type = "X"; break; + case CONF_RESV_NICK: type = "R"; break; + case CONF_RESV_CHANNEL: type = "R"; break; + default: + continue; + } + oper = aconf->info.oper; + if(aconf->flags & CONF_FLAGS_MYOPER) + { + /* Our operator{} names may not be meaningful + * to other servers, so rewrite to our server + * name. + */ + rb_strlcpy(operbuf, aconf->info.oper, sizeof buf); + p = strrchr(operbuf, '{'); + if (operbuf + sizeof operbuf - p > (ptrdiff_t)(melen + 2)) + { + memcpy(p + 1, me.name, melen); + p[melen + 1] = '}'; + p[melen + 2] = '\0'; + oper = operbuf; + } + } + sendto_one(client_p, ":%s BAN %c %s %s %s %lu %d %d %s :%s%s%s", + me.id, + aconf->status & CONF_ILLEGAL ? '-' : '+', + type, + aconf->user ? aconf->user : "*", aconf->host, + (unsigned long)aconf->created, + (int)(aconf->hold - aconf->created), + (int)(aconf->lifetime - aconf->created), + oper, + aconf->passwd, + aconf->spasswd ? "|" : "", + aconf->spasswd ? aconf->spasswd : ""); + } +} + /* burst_modes_TS6() * * input - client to burst to, channel name, list to burst, mode flag @@ -881,6 +943,9 @@ server_estab(struct Client *client_p) target_p->serv->fullcaps); } + if(IsCapable(client_p, CAP_BAN)) + burst_ban(client_p); + burst_TS6(client_p); /* Always send a PING after connect burst is done */ From a4893a45bed9c49cfd5fbab93546939d88892279 Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Fri, 5 Mar 2010 22:05:15 +0100 Subject: [PATCH 14/32] Use memmove instead of memcpy where there is overlap (modunload). --- src/modules.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules.c b/src/modules.c index 25d8cc7..189df07 100644 --- a/src/modules.c +++ b/src/modules.c @@ -881,7 +881,7 @@ unload_one_module(const char *name, int warn) dlclose(modlist[modindex]->address); rb_free(modlist[modindex]->name); - memcpy(&modlist[modindex], &modlist[modindex + 1], + memmove(&modlist[modindex], &modlist[modindex + 1], sizeof(struct module) * ((num_mods - 1) - modindex)); if(num_mods != 0) From e49d8185794e0e5013f7aedfebf56de4846308ee Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Fri, 5 Mar 2010 22:51:47 +0100 Subject: [PATCH 15/32] Remove +/- from the BAN message, instead indicating unban with duration=0. A kline must now last at least one second since its creation time. Also add better logic for bans that have already expired when they come in. --- modules/core/m_ban.c | 74 ++++++++++++++++++++------------------------ modules/m_kline.c | 10 ++++-- src/s_serv.c | 3 +- 3 files changed, 42 insertions(+), 45 deletions(-) diff --git a/modules/core/m_ban.c b/modules/core/m_ban.c index fb19c57..9f26c1b 100644 --- a/modules/core/m_ban.c +++ b/modules/core/m_ban.c @@ -47,7 +47,7 @@ static int ms_ban(struct Client *client_p, struct Client *source_p, int parc, co struct Message ban_msgtab = { "BAN", 0, 0, 0, MFLG_SLOW, - {mg_unreg, mg_ignore, {ms_ban, 10}, {ms_ban, 10}, mg_ignore, mg_ignore} + {mg_unreg, mg_ignore, {ms_ban, 9}, {ms_ban, 9}, mg_ignore, mg_ignore} }; mapi_clist_av1 ban_clist[] = { &ban_msgtab, NULL }; @@ -55,15 +55,14 @@ DECLARE_MODULE_AV1(ban, NULL, NULL, ban_clist, NULL, NULL, "$Revision: 1349 $"); /* ms_ban() * - * parv[1] - +/- - * parv[2] - type - * parv[3] - username mask or * - * parv[4] - hostname mask - * parv[5] - creation TS - * parv[6] - duration (relative to creation) - * parv[7] - lifetime (relative to creation) - * parv[8] - oper or * - * parv[9] - reason (possibly with |operreason) + * parv[1] - type + * parv[2] - username mask or * + * parv[3] - hostname mask + * parv[4] - creation TS + * parv[5] - duration (relative to creation) + * parv[6] - lifetime (relative to creation) + * parv[7] - oper or * + * parv[8] - reason (possibly with |operreason) */ static int ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) @@ -76,21 +75,14 @@ ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *p char *p; int act; - if (strcmp(parv[1], "+") && strcmp(parv[1], "-")) - { - sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, - "Unknown BAN operation %s from %s", - parv[1], source_p->name); - return 0; - } - if (strlen(parv[2]) != 1) + if (strlen(parv[1]) != 1) { sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "Unknown BAN type %s from %s", - parv[2], source_p->name); + parv[1], source_p->name); return 0; } - switch (parv[2][0]) + switch (parv[1][0]) { case 'K': ntype = CONF_KILL; @@ -99,17 +91,17 @@ ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *p default: sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "Unknown BAN type %s from %s", - parv[2], source_p->name); + parv[1], source_p->name); return 0; } - created = atol(parv[5]); - hold = created + atoi(parv[6]); - lifetime = created + atoi(parv[7]); - if (!strcmp(parv[8], "*")) + created = atol(parv[4]); + hold = created + atoi(parv[5]); + lifetime = created + atoi(parv[6]); + if (!strcmp(parv[7], "*")) oper = IsServer(source_p) ? source_p->name : get_oper_name(source_p); else - oper = parv[8]; - ptr = find_prop_ban(ntype, parv[3], parv[4]); + oper = parv[7]; + ptr = find_prop_ban(ntype, parv[2], parv[3]); if (ptr != NULL) { aconf = ptr->data; @@ -124,7 +116,8 @@ ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *p aconf->host); return 0; } - act = !(aconf->status & CONF_ILLEGAL) || !strcmp(parv[1], "+"); + act = !(aconf->status & CONF_ILLEGAL) || (hold != created && + hold > rb_current_time()); if (lifetime > aconf->lifetime) aconf->lifetime = lifetime; /* already expired, hmm */ @@ -148,12 +141,12 @@ ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *p aconf->status = CONF_ILLEGAL | ntype; aconf->lifetime = lifetime; rb_dlinkAddAlloc(aconf, &prop_bans); - act = !strcmp(parv[1], "+"); + act = hold != created && hold > rb_current_time(); } aconf->flags &= ~CONF_FLAGS_MYOPER; aconf->flags |= CONF_FLAGS_TEMPORARY; - aconf->user = ntype == CONF_KILL ? rb_strdup(parv[3]) : NULL; - aconf->host = rb_strdup(parv[4]); + aconf->user = ntype == CONF_KILL ? rb_strdup(parv[2]) : NULL; + aconf->host = rb_strdup(parv[3]); aconf->info.oper = operhash_add(oper); aconf->created = created; aconf->hold = hold; @@ -165,7 +158,7 @@ ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *p aconf->passwd = rb_strndup(parv[parc - 1], p - parv[parc - 1] + 1); aconf->spasswd = rb_strdup(p + 1); } - if (!strcmp(parv[1], "+")) + if (act && hold != created) { /* Keep the notices in sync with modules/m_kline.c etc. */ sendto_realops_snomask(SNO_GENERAL, L_ALL, @@ -173,18 +166,18 @@ ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *p IsServer(source_p) ? source_p->name : get_oper_name(source_p), (hold - rb_current_time()) / 60, stype, - strcmp(parv[8], "*") ? " from " : "", - strcmp(parv[8], "*") ? parv[8] : "", + strcmp(parv[7], "*") ? " from " : "", + strcmp(parv[7], "*") ? parv[7] : "", aconf->user ? aconf->user : "", aconf->user ? "@" : "", aconf->host, parv[parc - 1]); - aconf->status &= ~CONF_ILLEGAL; - ilog(L_KLINE, "%s %s %d %s %s %s", parv[2], + ilog(L_KLINE, "%s %s %d %s %s %s", parv[1], IsServer(source_p) ? source_p->name : get_oper_name(source_p), (hold - rb_current_time()) / 60, aconf->user, aconf->host, parv[parc - 1]); + aconf->status &= ~CONF_ILLEGAL; } else if (act) { @@ -195,9 +188,9 @@ ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *p aconf->user ? aconf->user : "", aconf->user ? "@" : "", aconf->host, - strcmp(parv[8], "*") ? " on behalf of " : "", - strcmp(parv[8], "*") ? parv[8] : ""); - ilog(L_KLINE, "U%s %s %s %s", parv[2], + strcmp(parv[7], "*") ? " on behalf of " : "", + strcmp(parv[7], "*") ? parv[7] : ""); + ilog(L_KLINE, "U%s %s %s %s", parv[1], IsServer(source_p) ? source_p->name : get_oper_name(source_p), aconf->user, aconf->host); } @@ -226,7 +219,7 @@ ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *p break; } sendto_server(NULL, NULL, CAP_BAN|CAP_TS6, NOCAPS, - ":%s BAN %s %s %s %s %s %s %s %s :%s", + ":%s BAN %s %s %s %s %s %s %s :%s", source_p->id, parv[1], parv[2], @@ -235,7 +228,6 @@ ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *p parv[5], parv[6], parv[7], - parv[8], parv[parc - 1]); return 0; } diff --git a/modules/m_kline.c b/modules/m_kline.c index 4ba0561..c532c0a 100644 --- a/modules/m_kline.c +++ b/modules/m_kline.c @@ -584,6 +584,11 @@ apply_prop_kline(struct Client *source_p, struct ConfItem *aconf, /* Force creation time to increase. */ if(oldconf->created >= aconf->created) aconf->created = oldconf->created + 1; + /* Leave at least one second of validity. */ + if(aconf->hold <= aconf->created) + aconf->hold = aconf->created + 1; + if(aconf->lifetime < aconf->hold) + aconf->lifetime = aconf->hold; /* Tell deactivate_conf() to destroy it. */ oldconf->lifetime = rb_current_time(); deactivate_conf(oldconf, ptr); @@ -617,7 +622,7 @@ apply_prop_kline(struct Client *source_p, struct ConfItem *aconf, tkline_time / 60, aconf->user, aconf->host); sendto_server(NULL, NULL, CAP_BAN|CAP_TS6, NOCAPS, - ":%s BAN + K %s %s %lu %d %d * :%s%s%s", + ":%s BAN K %s %s %lu %d %d * :%s%s%s", source_p->id, aconf->user, aconf->host, (unsigned long)aconf->created, (int)(aconf->hold - aconf->created), @@ -922,11 +927,12 @@ remove_prop_kline(struct Client *source_p, struct ConfItem *aconf) aconf->created = rb_current_time(); else aconf->created++; + aconf->hold = aconf->created; operhash_delete(aconf->info.oper); aconf->info.oper = operhash_add(get_oper_name(source_p)); aconf->flags |= CONF_FLAGS_MYOPER | CONF_FLAGS_TEMPORARY; sendto_server(NULL, NULL, CAP_BAN|CAP_TS6, NOCAPS, - ":%s BAN - K %s %s %lu %d %d * :*", + ":%s BAN K %s %s %lu %d %d * :*", source_p->id, aconf->user, aconf->host, (unsigned long)aconf->created, 0, diff --git a/src/s_serv.c b/src/s_serv.c index e71b1f3..2f8b6b5 100644 --- a/src/s_serv.c +++ b/src/s_serv.c @@ -439,9 +439,8 @@ burst_ban(struct Client *client_p) oper = operbuf; } } - sendto_one(client_p, ":%s BAN %c %s %s %s %lu %d %d %s :%s%s%s", + sendto_one(client_p, ":%s BAN %s %s %s %lu %d %d %s :%s%s%s", me.id, - aconf->status & CONF_ILLEGAL ? '-' : '+', type, aconf->user ? aconf->user : "*", aconf->host, (unsigned long)aconf->created, From 05114b16a3b89846e7be89e7622e5b165bdba6b0 Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Fri, 5 Mar 2010 22:53:35 +0100 Subject: [PATCH 16/32] BAN: Avoid fake direction. --- modules/core/m_ban.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/core/m_ban.c b/modules/core/m_ban.c index 9f26c1b..5341d2e 100644 --- a/modules/core/m_ban.c +++ b/modules/core/m_ban.c @@ -218,7 +218,7 @@ ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *p } break; } - sendto_server(NULL, NULL, CAP_BAN|CAP_TS6, NOCAPS, + sendto_server(client_p, NULL, CAP_BAN|CAP_TS6, NOCAPS, ":%s BAN %s %s %s %s %s %s %s :%s", source_p->id, parv[1], From c177d078ea560e07276f94948f5287a8feb1b5fe Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Fri, 5 Mar 2010 23:16:28 +0100 Subject: [PATCH 17/32] Among bans with the same creation time, prefer the one with longest lifetime. --- modules/core/m_ban.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/core/m_ban.c b/modules/core/m_ban.c index 5341d2e..8d4f269 100644 --- a/modules/core/m_ban.c +++ b/modules/core/m_ban.c @@ -105,7 +105,9 @@ ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *p if (ptr != NULL) { aconf = ptr->data; - if (aconf->created >= created) + if (aconf->created > created || + (aconf->created == created && + aconf->lifetime >= lifetime)) { if (IsPerson(source_p)) sendto_one_notice(source_p, From 20eef930041ff0bdda148fd1ec82adc8128d0d05 Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Sat, 6 Mar 2010 00:31:51 +0100 Subject: [PATCH 18/32] Add /stats g to show propagated (global) klines. --- help/opers/stats | 1 + modules/m_stats.c | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/help/opers/stats b/help/opers/stats index 3017eb3..5d25900 100644 --- a/help/opers/stats +++ b/help/opers/stats @@ -16,6 +16,7 @@ X B - Shows hash statistics * e - Shows exemptions to D lines X E - Shows Events X f - Shows File Descriptors +* g - Shows global K lines ^ h - Shows hub_mask/leaf_mask (Old H:/L: lines) ^ i - Shows auth blocks (Old I: lines) ^ K - Shows K lines (or matched klines) diff --git a/modules/m_stats.c b/modules/m_stats.c index f621270..67e53bb 100644 --- a/modules/m_stats.c +++ b/modules/m_stats.c @@ -94,6 +94,7 @@ static void stats_tdeny(struct Client *); static void stats_deny(struct Client *); static void stats_exempt(struct Client *); static void stats_events(struct Client *); +static void stats_prop_klines(struct Client *); static void stats_hubleaf(struct Client *); static void stats_auth(struct Client *); static void stats_tklines(struct Client *); @@ -137,6 +138,7 @@ static struct StatsStruct stats_cmd_table[] = { {'E', stats_events, 1, 1, }, {'f', stats_comm, 1, 1, }, {'F', stats_comm, 1, 1, }, + {'g', stats_prop_klines, 1, 0, }, {'h', stats_hubleaf, 0, 0, }, {'H', stats_hubleaf, 0, 0, }, {'i', stats_auth, 0, 0, }, @@ -450,6 +452,32 @@ stats_events (struct Client *source_p) rb_dump_events(stats_events_cb, source_p); } +static void +stats_prop_klines(struct Client *source_p) +{ + struct ConfItem *aconf; + rb_dlink_node *ptr; + char *user, *host, *pass, *oper_reason; + + RB_DLINK_FOREACH(ptr, prop_bans.head) + { + aconf = ptr->data; + + /* Skip non-klines and deactivated klines. */ + if(aconf->status != CONF_KILL) + continue; + + get_printable_kline(source_p, aconf, &host, &pass, + &user, &oper_reason); + + sendto_one_numeric(source_p, RPL_STATSKLINE, + form_str(RPL_STATSKLINE), + 'g', host, user, pass, + oper_reason ? "|" : "", + oper_reason ? oper_reason : ""); + } +} + static void stats_hubleaf(struct Client *source_p) { From 70fd7fc9fbd1e12a2f65fd29da84a0f19e9fabe7 Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Sat, 6 Mar 2010 01:45:41 +0100 Subject: [PATCH 19/32] BAN: Reject bans with insufficient non-wildcard characters. Such bans are not applied locally, but are propagated normally. They can only be removed on a server that applies them. Note that normally KLINE will not accept such bans. This is mainly for services, differing min_wildcard and ircd changes. --- include/s_conf.h | 1 + modules/core/m_ban.c | 27 ++++++++++++++- modules/m_kline.c | 82 +++++++++++--------------------------------- src/s_conf.c | 56 ++++++++++++++++++++++++++++++ 4 files changed, 103 insertions(+), 63 deletions(-) diff --git a/include/s_conf.h b/include/s_conf.h index 6573e7b..a535d93 100644 --- a/include/s_conf.h +++ b/include/s_conf.h @@ -370,6 +370,7 @@ extern void yyerror(const char *); extern int conf_yy_fatal_error(const char *); extern int conf_fgets(char *, int, FILE *); +extern int valid_wild_card(const char *, const char *); extern void add_temp_kline(struct ConfItem *); extern void add_temp_dline(struct ConfItem *); extern void report_temp_klines(struct Client *); diff --git a/modules/core/m_ban.c b/modules/core/m_ban.c index 8d4f269..f61ba07 100644 --- a/modules/core/m_ban.c +++ b/modules/core/m_ban.c @@ -35,6 +35,7 @@ #include "ircd.h" #include "match.h" #include "s_conf.h" +#include "s_newconf.h" #include "msg.h" #include "modules.h" #include "hash.h" @@ -160,7 +161,31 @@ ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *p aconf->passwd = rb_strndup(parv[parc - 1], p - parv[parc - 1] + 1); aconf->spasswd = rb_strdup(p + 1); } - if (act && hold != created) + if (act && hold != created && + !(ntype == CONF_KILL ? + valid_wild_card(aconf->user, aconf->host) : + valid_wild_card_simple(aconf->host))) + { + sendto_realops_snomask(SNO_GENERAL, L_ALL, + "Ignoring global %d min. %s from %s%s%s for [%s%s%s]: too few non-wildcard characters", + (hold - rb_current_time()) / 60, + stype, + IsServer(source_p) ? source_p->name : get_oper_name(source_p), + strcmp(parv[7], "*") ? " on behalf of " : "", + strcmp(parv[7], "*") ? parv[7] : "", + aconf->user ? aconf->user : "", + aconf->user ? "@" : "", + aconf->host); + if(IsPerson(source_p)) + sendto_one_notice(source_p, + ":Your %s [%s%s%s] has too few non-wildcard characters", + stype, + aconf->user ? aconf->user : "", + aconf->user ? "@" : "", + aconf->host); + /* Propagate it, but do not apply it locally. */ + } + else if (act && hold != created) { /* Keep the notices in sync with modules/m_kline.c etc. */ sendto_realops_snomask(SNO_GENERAL, L_ALL, diff --git a/modules/m_kline.c b/modules/m_kline.c index c532c0a..46ff730 100644 --- a/modules/m_kline.c +++ b/modules/m_kline.c @@ -71,7 +71,6 @@ DECLARE_MODULE_AV1(kline, NULL, NULL, kline_clist, NULL, NULL, "$Revision$"); static int find_user_host(struct Client *source_p, const char *userhost, char *user, char *host); static int valid_comment(struct Client *source_p, char *comment); static int valid_user_host(struct Client *source_p, const char *user, const char *host); -static int valid_wild_card(struct Client *source_p, const char *user, const char *host); static void handle_remote_kline(struct Client *source_p, int tkline_time, const char *user, const char *host, const char *reason); @@ -168,9 +167,18 @@ mo_kline(struct Client *client_p, struct Client *source_p, int parc, const char "%lu %s %s :%s", tkline_time, user, host, reason); if(!valid_user_host(source_p, user, host) || - !valid_wild_card(source_p, user, host) || !valid_comment(source_p, reason)) + !valid_comment(source_p, reason)) return 0; + if(!valid_wild_card(user, host)) + { + sendto_one_notice(source_p, + ":Please include at least %d non-wildcard " + "characters with the user@host", + ConfigFileEntry.min_nonwildcard); + return 0; + } + if(propagated && tkline_time == 0) { sendto_one_notice(source_p, ":Cannot set a permanent global ban"); @@ -280,9 +288,18 @@ handle_remote_kline(struct Client *source_p, int tkline_time, return; if(!valid_user_host(source_p, user, host) || - !valid_wild_card(source_p, user, host) || !valid_comment(source_p, reason)) + !valid_comment(source_p, reason)) return; + if(!valid_wild_card(user, host)) + { + sendto_one_notice(source_p, + ":Please include at least %d non-wildcard " + "characters with the user@host", + ConfigFileEntry.min_nonwildcard); + return 0; + } + if(already_placed_kline(source_p, user, host, tkline_time)) return; @@ -695,65 +712,6 @@ valid_user_host(struct Client *source_p, const char *luser, const char *lhost) return 1; } -/* valid_wild_card() - * - * input - user buffer, host buffer - * output - 0 if invalid, 1 if valid - * side effects - - */ -static int -valid_wild_card(struct Client *source_p, const char *luser, const char *lhost) -{ - const char *p; - char tmpch; - int nonwild = 0; - int bitlen; - - /* user has no wildcards, always accept -- jilles */ - if(!strchr(luser, '?') && !strchr(luser, '*')) - return 1; - - /* check there are enough non wildcard chars */ - p = luser; - while((tmpch = *p++)) - { - if(!IsKWildChar(tmpch)) - { - /* found enough chars, return */ - if(++nonwild >= ConfigFileEntry.min_nonwildcard) - return 1; - } - } - - /* try host, as user didnt contain enough */ - /* special case for cidr masks -- jilles */ - if((p = strrchr(lhost, '/')) != NULL && IsDigit(p[1])) - { - bitlen = atoi(p + 1); - /* much like non-cidr for ipv6, rather arbitrary for ipv4 */ - if(bitlen > 0 - && bitlen >= - (strchr(lhost, ':') ? 4 * (ConfigFileEntry.min_nonwildcard - nonwild) : 6 - - 2 * nonwild)) - return 1; - } - else - { - p = lhost; - while((tmpch = *p++)) - { - if(!IsKWildChar(tmpch)) - if(++nonwild >= ConfigFileEntry.min_nonwildcard) - return 1; - } - } - - sendto_one_notice(source_p, - ":Please include at least %d non-wildcard " - "characters with the user@host", ConfigFileEntry.min_nonwildcard); - return 0; -} - /* * valid_comment * inputs - pointer to client diff --git a/src/s_conf.c b/src/s_conf.c index 55a9728..5775387 100644 --- a/src/s_conf.c +++ b/src/s_conf.c @@ -1007,6 +1007,62 @@ add_temp_dline(struct ConfItem *aconf) add_conf_by_address(aconf->host, CONF_DLINE, aconf->user, NULL, aconf); } +/* valid_wild_card() + * + * input - user buffer, host buffer + * output - 0 if invalid, 1 if valid + * side effects - + */ +int +valid_wild_card(const char *luser, const char *lhost) +{ + const char *p; + char tmpch; + int nonwild = 0; + int bitlen; + + /* user has no wildcards, always accept -- jilles */ + if(!strchr(luser, '?') && !strchr(luser, '*')) + return 1; + + /* check there are enough non wildcard chars */ + p = luser; + while((tmpch = *p++)) + { + if(!IsKWildChar(tmpch)) + { + /* found enough chars, return */ + if(++nonwild >= ConfigFileEntry.min_nonwildcard) + return 1; + } + } + + /* try host, as user didnt contain enough */ + /* special case for cidr masks -- jilles */ + if((p = strrchr(lhost, '/')) != NULL && IsDigit(p[1])) + { + bitlen = atoi(p + 1); + /* much like non-cidr for ipv6, rather arbitrary for ipv4 */ + if(bitlen > 0 + && bitlen >= + (strchr(lhost, ':') ? 4 * (ConfigFileEntry.min_nonwildcard - nonwild) : 6 - + 2 * nonwild)) + return 1; + } + else + { + p = lhost; + while((tmpch = *p++)) + { + if(!IsKWildChar(tmpch)) + if(++nonwild >= ConfigFileEntry.min_nonwildcard) + return 1; + } + } + + return 0; +} + rb_dlink_node * find_prop_ban(unsigned int status, const char *user, const char *host) { From c3666dd012bbb789f1c1f2d942a0eddf3f4dbf2a Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Sat, 6 Mar 2010 16:37:50 +0100 Subject: [PATCH 20/32] Avoid crash if get_oper_name() somehow gave no {} for local oper. --- src/s_serv.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/s_serv.c b/src/s_serv.c index 2f8b6b5..2569d56 100644 --- a/src/s_serv.c +++ b/src/s_serv.c @@ -431,7 +431,8 @@ burst_ban(struct Client *client_p) */ rb_strlcpy(operbuf, aconf->info.oper, sizeof buf); p = strrchr(operbuf, '{'); - if (operbuf + sizeof operbuf - p > (ptrdiff_t)(melen + 2)) + if (p != NULL && + operbuf + sizeof operbuf - p > (ptrdiff_t)(melen + 2)) { memcpy(p + 1, me.name, melen); p[melen + 1] = '}'; From 03ad38143bf9e96e8825f01e49f0f25afdcc70ef Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Sat, 6 Mar 2010 22:27:54 +0100 Subject: [PATCH 21/32] Hgignore some generated files. --- .hgignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.hgignore b/.hgignore index eab4df7..3add8a5 100644 --- a/.hgignore +++ b/.hgignore @@ -10,6 +10,8 @@ Makefile .deps .libs autom4te.cache +bandb/bandb +bandb/bantool config.log config.status include/setup.h @@ -18,6 +20,7 @@ libratbox/include/librb-config.h libratbox/include/stamp-h1 libratbox/libratbox.pc libratbox/libtool +libratbox/src/version.c scripts/*.tbz2 scripts/*.tgz servlink/servlink From f8cebd00f207fdbb5466ad25a5a13b059e1b671a Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Sat, 6 Mar 2010 22:37:42 +0100 Subject: [PATCH 22/32] Show d/kline setter to opers in stats/testline. --- src/s_conf.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/s_conf.c b/src/s_conf.c index 5775387..ffa0e8a 100644 --- a/src/s_conf.c +++ b/src/s_conf.c @@ -1322,15 +1322,22 @@ get_printable_kline(struct Client *source_p, struct ConfItem *aconf, char **user, char **oper_reason) { static char null[] = ""; + static char operreasonbuf[BUFSIZE]; *host = EmptyString(aconf->host) ? null : aconf->host; *user = EmptyString(aconf->user) ? null : aconf->user; *reason = get_user_ban_reason(aconf); - if(EmptyString(aconf->spasswd) || !IsOper(source_p)) + if(!IsOper(source_p)) *oper_reason = NULL; else - *oper_reason = aconf->spasswd; + { + rb_snprintf(operreasonbuf, sizeof operreasonbuf, "%s%s(%s)", + EmptyString(aconf->spasswd) ? "" : aconf->spasswd, + EmptyString(aconf->spasswd) ? "" : " ", + aconf->info.oper); + *oper_reason = operreasonbuf; + } } /* From dc082cb0547098dc4a8d233f769edb2143acd800 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Sat, 6 Mar 2010 21:01:19 -0600 Subject: [PATCH 23/32] Update CREDITS. --- CREDITS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CREDITS b/CREDITS index 5fd4939..68dcd9a 100644 --- a/CREDITS +++ b/CREDITS @@ -17,8 +17,6 @@ network configurations. The charybdis core team is listed in nick-alphabetical order: -dwr, Valery Yatsko -gxti, Michael Tharp jilles, Jilles Tjoelker nenolod, William Pitcock @@ -28,7 +26,9 @@ in nick-alphabetical order: AndroSyn, Aaron Sethman anfl, Lee Hardy beu, Elfyn McBratney +dwr, Valery Yatsko Entrope, Michael Poole +gxti, Michael Tharp spb, Stephen Bennett ThaPrince, Jon Christopherson twincest, River Tarnell From 517967618d57f91ac7fa46ee5f76d62c9d0f39ef Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Sun, 7 Mar 2010 14:06:28 +0100 Subject: [PATCH 24/32] Document BAN message. --- doc/technical/ts6-protocol.txt | 45 +++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/doc/technical/ts6-protocol.txt b/doc/technical/ts6-protocol.txt index d86e34c..902cdd7 100644 --- a/doc/technical/ts6-protocol.txt +++ b/doc/technical/ts6-protocol.txt @@ -55,10 +55,10 @@ send its own PASS, CAPAB and SERVER messages, followed by SVINFO and the burst. Upon receiving the SERVER, the initiator will send SVINFO and the burst. If ziplinks are used, SVINFO is the first compressed message. -The burst consists of SID and SERVER messages for all known servers, UID or -EUID messages for all known users (possibly followed by ENCAP REALHOST, ENCAP -LOGIN and/or AWAY) and SJOIN messages for all known channels (possibly followed -by BMASK and/or TB). +The burst consists of SID and SERVER messages for all known servers, BAN +messages for all propagated bans, UID or EUID messages for all known users +(possibly followed by ENCAP REALHOST, ENCAP LOGIN and/or AWAY) and SJOIN +messages for all known channels (possibly followed by BMASK and/or TB). user modes: (all) @@ -148,6 +148,43 @@ Otherwise, mark the user as away. Changing away reason from one non-empty string to another non-empty string may not be propagated. +BAN +charybdis TS6 +capab: BAN +source: any +propagation: broadcast (restricted) +parameters: type, user mask, host mask, creation TS, duration, lifetime, oper, reason + +Propagates a network wide ban. + +The type is K for K:lines; other types are reserved. + +The creation TS indicates when this ban was last modified. An incoming ban MUST +be ignored and not propagated if the creation TS is older than the creation TS +of the current ban. If the ban is identical, it SHOULD NOT be propagated to +avoid unnecessary network traffic. (Two changes to bans that set the TS to the +same value may cause desynchronization.) + +The duration is 0 for an unban and relative to the creation TS for a ban. +When the duration has passed, the ban is no longer active but it may still +be necessary to remember it. + +The lifetime is relative to the creation TS and indicates for how long this +ban needs to be remembered and propagated. This MUST be at least the duration. +Initially, it is usually set the same as the duration but when the ban is +modified later, it SHOULD be set such that the modified ban is remembered at +least as long as the original ban. This ensures that the original ban does not +revive via split servers. This requirement is only a SHOULD to allow for +implementations that only inject bans and do not remember any; implementations +that remember and propagate bans MUST set the lifetime appropriately. + +The oper field indicates the oper that originally set the ban. If this message +is the initial propagation of a change, it SHOULD be sent as * (an asterisk). + +The reason field indicates the reason for the ban. Any part after a | (vertical +bar) MUST NOT be shown to normal users. The rest of the field and the creation +TS and duration MAY be shown to normal users. + BMASK source: server propagation: broadcast From 504f309e38c6e5ae71d9ba2a6b5e401e03f042ae Mon Sep 17 00:00:00 2001 From: JD Horelick Date: Sat, 27 Mar 2010 14:58:04 -0400 Subject: [PATCH 25/32] Add option general::use_propagated_bans to allow disabling new KLINE. If this option is yes (default), KLINE by itself sets global (propagated) bans. If this option is no, KLINE by itself sets a local kline following cluster{}, compatible with 3.2 and older versions. --- doc/example.conf | 1 + doc/reference.conf | 7 +++++++ include/s_conf.h | 1 + modules/m_info.c | 6 ++++++ modules/m_kline.c | 2 +- src/newconf.c | 1 + src/s_conf.c | 1 + 7 files changed, 18 insertions(+), 1 deletion(-) diff --git a/doc/example.conf b/doc/example.conf index 3a852a4..aaf47cf 100755 --- a/doc/example.conf +++ b/doc/example.conf @@ -530,6 +530,7 @@ general { identify_command = "IDENTIFY"; non_redundant_klines = yes; warn_no_nline = yes; + use_propagated_bans = yes; stats_e_disabled = no; stats_c_oper_only=no; stats_h_oper_only=no; diff --git a/doc/reference.conf b/doc/reference.conf index 6c53d27..33f4a55 100755 --- a/doc/reference.conf +++ b/doc/reference.conf @@ -1198,6 +1198,13 @@ general { */ warn_no_nline = yes; + /* use propagated bans: KLINE sets fully propagated bans. That means + * the klines are part of the netburst and restarted/split servers + * will get them, but they will not apply to 3.2 and older servers + * at all. + */ + use_propagated_bans = yes; + /* stats e disabled: disable stats e. useful if server ips are * exempted and you dont want them listing on irc. */ diff --git a/include/s_conf.h b/include/s_conf.h index a535d93..0ee207a 100644 --- a/include/s_conf.h +++ b/include/s_conf.h @@ -229,6 +229,7 @@ struct config_file_entry int default_umodes; int global_snotices; int operspy_dont_care_user_info; + int use_propagated_bans; int secret_channels_in_whois; int expire_override_time; }; diff --git a/modules/m_info.c b/modules/m_info.c index 716ca9d..e829127 100644 --- a/modules/m_info.c +++ b/modules/m_info.c @@ -530,6 +530,12 @@ static struct InfoStruct info_table[] = { &ConfigFileEntry.warn_no_nline, "Display warning if connecting server lacks N-line" }, + { + "use_propagated_bans", + OUTPUT_BOOLEAN, + &ConfigFileEntry.use_propagated_bans, + "KLINE sets fully propagated bans" + }, { "default_split_server_count", OUTPUT_DECIMAL, diff --git a/modules/m_kline.c b/modules/m_kline.c index 46ff730..364c30b 100644 --- a/modules/m_kline.c +++ b/modules/m_kline.c @@ -107,7 +107,7 @@ mo_kline(struct Client *client_p, struct Client *source_p, int parc, const char struct ConfItem *aconf; int tkline_time = 0; int loc = 1; - int propagated = 1; + int propagated = ConfigFileEntry.use_propagated_bans; if(!IsOperK(source_p)) { diff --git a/src/newconf.c b/src/newconf.c index 18ea7fc..d71788a 100644 --- a/src/newconf.c +++ b/src/newconf.c @@ -2253,6 +2253,7 @@ static struct ConfEntry conf_general_table[] = { "ts_warn_delta", CF_TIME, NULL, 0, &ConfigFileEntry.ts_warn_delta }, { "use_whois_actually", CF_YESNO, NULL, 0, &ConfigFileEntry.use_whois_actually }, { "warn_no_nline", CF_YESNO, NULL, 0, &ConfigFileEntry.warn_no_nline }, + { "use_propagated_bans",CF_YESNO, NULL, 0, &ConfigFileEntry.use_propagated_bans }, { "expire_override_time", CF_TIME, NULL, 0, &ConfigFileEntry.expire_override_time}, { "\0", 0, NULL, 0, NULL } }; diff --git a/src/s_conf.c b/src/s_conf.c index ffa0e8a..3f46088 100644 --- a/src/s_conf.c +++ b/src/s_conf.c @@ -749,6 +749,7 @@ set_default_conf(void) ConfigFileEntry.collision_fnc = YES; ConfigFileEntry.global_snotices = YES; ConfigFileEntry.operspy_dont_care_user_info = NO; + ConfigFileEntry.use_propagated_bans = YES; ConfigFileEntry.secret_channels_in_whois = NO; #ifdef HAVE_LIBZ From 112e8a666b1c901d24b1883b257ce02cb6aa82ec Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Tue, 16 Mar 2010 23:05:50 +0100 Subject: [PATCH 26/32] Add propagated xlines, like klines. --- doc/reference.conf | 8 ++-- help/opers/stats | 2 +- include/s_conf.h | 1 + modules/core/m_ban.c | 25 +++++++++-- modules/m_kline.c | 23 +--------- modules/m_xline.c | 104 +++++++++++++++++++++++++++++++++++++------ src/s_conf.c | 30 +++++++++++++ 7 files changed, 149 insertions(+), 44 deletions(-) diff --git a/doc/reference.conf b/doc/reference.conf index 33f4a55..c46ffa8 100755 --- a/doc/reference.conf +++ b/doc/reference.conf @@ -1198,10 +1198,10 @@ general { */ warn_no_nline = yes; - /* use propagated bans: KLINE sets fully propagated bans. That means - * the klines are part of the netburst and restarted/split servers - * will get them, but they will not apply to 3.2 and older servers - * at all. + /* use propagated bans: KLINE and XLINE set fully propagated bans. + * That means the bans are part of the netburst and restarted/split + * servers will get them, but they will not apply to 3.2 and older + * servers at all. */ use_propagated_bans = yes; diff --git a/help/opers/stats b/help/opers/stats index 5d25900..f20ad56 100644 --- a/help/opers/stats +++ b/help/opers/stats @@ -36,7 +36,7 @@ X f - Shows File Descriptors * U - Shows shared blocks (Old U: lines) u - Shows server uptime ^ v - Shows connected servers and brief status information -* x - Shows temporary gecos bans +* x - Shows temporary and global gecos bans * X - Shows gecos bans (Old X: lines) ^ y - Shows connection classes (Old Y: lines) * z - Shows memory stats diff --git a/include/s_conf.h b/include/s_conf.h index 0ee207a..31b9a74 100644 --- a/include/s_conf.h +++ b/include/s_conf.h @@ -351,6 +351,7 @@ extern void free_conf(struct ConfItem *); extern rb_dlink_node *find_prop_ban(unsigned int status, const char *user, const char *host); extern void deactivate_conf(struct ConfItem *, rb_dlink_node *); +extern void replace_old_ban(struct ConfItem *); extern void read_conf_files(int cold); diff --git a/modules/core/m_ban.c b/modules/core/m_ban.c index f61ba07..0efe6ef 100644 --- a/modules/core/m_ban.c +++ b/modules/core/m_ban.c @@ -89,6 +89,10 @@ ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *p ntype = CONF_KILL; stype = "K-Line"; break; + case 'X': + ntype = CONF_XLINE; + stype = "X-Line"; + break; default: sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "Unknown BAN type %s from %s", @@ -199,10 +203,12 @@ ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *p aconf->user ? "@" : "", aconf->host, parv[parc - 1]); - ilog(L_KLINE, "%s %s %d %s %s %s", parv[1], + ilog(L_KLINE, "%s %s %d %s%s%s %s", parv[1], IsServer(source_p) ? source_p->name : get_oper_name(source_p), (hold - rb_current_time()) / 60, - aconf->user, aconf->host, + aconf->user ? aconf->user : "", + aconf->user ? " " : "", + aconf->host, parv[parc - 1]); aconf->status &= ~CONF_ILLEGAL; } @@ -217,9 +223,11 @@ ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *p aconf->host, strcmp(parv[7], "*") ? " on behalf of " : "", strcmp(parv[7], "*") ? parv[7] : ""); - ilog(L_KLINE, "U%s %s %s %s", parv[1], + ilog(L_KLINE, "U%s %s %s%s %s", parv[1], IsServer(source_p) ? source_p->name : get_oper_name(source_p), - aconf->user, aconf->host); + aconf->user ? aconf->user : "", + aconf->user ? " " : "", + aconf->host); } switch (ntype) { @@ -244,6 +252,15 @@ ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *p check_klines(); } break; + case CONF_XLINE: + if (aconf->status & CONF_ILLEGAL) + remove_reject_mask(aconf->host, NULL); + else + { + rb_dlinkAddAlloc(aconf, &xline_conf_list); + check_xlines(); + } + break; } sendto_server(client_p, NULL, CAP_BAN|CAP_TS6, NOCAPS, ":%s BAN %s %s %s %s %s %s %s :%s", diff --git a/modules/m_kline.c b/modules/m_kline.c index 364c30b..d6e22bc 100644 --- a/modules/m_kline.c +++ b/modules/m_kline.c @@ -584,32 +584,11 @@ static void apply_prop_kline(struct Client *source_p, struct ConfItem *aconf, const char *reason, const char *oper_reason, int tkline_time) { - rb_dlink_node *ptr; - struct ConfItem *oldconf; - aconf->flags |= CONF_FLAGS_MYOPER | CONF_FLAGS_TEMPORARY; aconf->hold = rb_current_time() + tkline_time; aconf->lifetime = aconf->hold; - ptr = find_prop_ban(aconf->status, aconf->user, aconf->host); - if(ptr != NULL) - { - oldconf = ptr->data; - /* Remember at least as long as the old one. */ - if(oldconf->lifetime > aconf->lifetime) - aconf->lifetime = oldconf->lifetime; - /* Force creation time to increase. */ - if(oldconf->created >= aconf->created) - aconf->created = oldconf->created + 1; - /* Leave at least one second of validity. */ - if(aconf->hold <= aconf->created) - aconf->hold = aconf->created + 1; - if(aconf->lifetime < aconf->hold) - aconf->lifetime = aconf->hold; - /* Tell deactivate_conf() to destroy it. */ - oldconf->lifetime = rb_current_time(); - deactivate_conf(oldconf, ptr); - } + replace_old_ban(aconf); rb_dlinkAddAlloc(aconf, &prop_bans); add_conf_by_address(aconf->host, CONF_KILL, aconf->user, NULL, aconf); diff --git a/modules/m_xline.c b/modules/m_xline.c index 556ad00..566a369 100644 --- a/modules/m_xline.c +++ b/modules/m_xline.c @@ -79,7 +79,7 @@ DECLARE_MODULE_AV1(xline, NULL, NULL, xline_clist, NULL, NULL, "$Revision$"); static int valid_xline(struct Client *, const char *, const char *); static void apply_xline(struct Client *client_p, const char *name, - const char *reason, int temp_time); + const char *reason, int temp_time, int propagated); static void propagate_xline(struct Client *source_p, const char *target, int temp_time, const char *name, const char *type, const char *reason); static void cluster_xline(struct Client *source_p, int temp_time, @@ -89,7 +89,8 @@ static void handle_remote_xline(struct Client *source_p, int temp_time, const char *name, const char *reason); static void handle_remote_unxline(struct Client *source_p, const char *name); -static void remove_xline(struct Client *source_p, const char *name); +static void remove_xline(struct Client *source_p, const char *name, + int propagated); /* m_xline() @@ -107,6 +108,7 @@ mo_xline(struct Client *client_p, struct Client *source_p, int parc, const char const char *target_server = NULL; int temp_time; int loc = 1; + int propagated = ConfigFileEntry.use_propagated_bans; if(!IsOperXline(source_p)) { @@ -152,8 +154,11 @@ mo_xline(struct Client *client_p, struct Client *source_p, int parc, const char if(!match(target_server, me.name)) return 0; + + /* Set as local-only. */ + propagated = 0; } - else if(rb_dlink_list_length(&cluster_conf_list) > 0) + else if(!propagated && rb_dlink_list_length(&cluster_conf_list) > 0) cluster_xline(source_p, temp_time, name, reason); if((aconf = find_xline_mask(name)) != NULL) @@ -166,7 +171,13 @@ mo_xline(struct Client *client_p, struct Client *source_p, int parc, const char if(!valid_xline(source_p, name, reason)) return 0; - apply_xline(source_p, name, reason, temp_time); + if(propagated && temp_time == 0) + { + sendto_one_notice(source_p, ":Cannot set a permanent global ban"); + return 0; + } + + apply_xline(source_p, name, reason, temp_time, propagated); return 0; } @@ -226,7 +237,7 @@ handle_remote_xline(struct Client *source_p, int temp_time, const char *name, co return; } - apply_xline(source_p, name, reason, temp_time); + apply_xline(source_p, name, reason, temp_time, 0); } /* valid_xline() @@ -270,8 +281,9 @@ valid_xline(struct Client *source_p, const char *gecos, const char *reason) } void -apply_xline(struct Client *source_p, const char *name, const char *reason, int temp_time) +apply_xline(struct Client *source_p, const char *name, const char *reason, int temp_time, int propagated) { + rb_dlink_node *ptr; struct ConfItem *aconf; aconf = make_conf(); @@ -283,7 +295,32 @@ apply_xline(struct Client *source_p, const char *name, const char *reason, int t aconf->info.oper = operhash_add(get_oper_name(source_p)); - if(temp_time > 0) + if(propagated) + { + aconf->flags |= CONF_FLAGS_MYOPER | CONF_FLAGS_TEMPORARY; + aconf->hold = rb_current_time() + temp_time; + aconf->lifetime = aconf->hold; + + replace_old_ban(aconf); + rb_dlinkAddAlloc(aconf, &prop_bans); + + sendto_realops_snomask(SNO_GENERAL, L_ALL, + "%s added global %d min. X-Line for [%s] [%s]", + get_oper_name(source_p), temp_time / 60, + aconf->host, reason); + ilog(L_KLINE, "X %s %d %s %s", + get_oper_name(source_p), temp_time / 60, name, reason); + sendto_one_notice(source_p, ":Added global %d min. X-Line [%s]", + temp_time / 60, aconf->host); + sendto_server(NULL, NULL, CAP_BAN|CAP_TS6, NOCAPS, + ":%s BAN X * %s %lu %d %d * :%s", + source_p->id, aconf->host, + (unsigned long)aconf->created, + (int)(aconf->hold - aconf->created), + (int)(aconf->lifetime - aconf->created), + reason); + } + else if(temp_time > 0) { aconf->hold = rb_current_time() + temp_time; @@ -366,6 +403,8 @@ cluster_xline(struct Client *source_p, int temp_time, const char *name, const ch static int mo_unxline(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { + int propagated = 1; + if(!IsOperXline(source_p)) { sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name, "xline"); @@ -385,11 +424,12 @@ mo_unxline(struct Client *client_p, struct Client *source_p, int parc, const cha if(match(parv[3], me.name) == 0) return 0; - } - else if(rb_dlink_list_length(&cluster_conf_list)) - cluster_generic(source_p, "UNXLINE", SHARED_UNXLINE, CAP_CLUSTER, "%s", parv[1]); - remove_xline(source_p, parv[1]); + propagated = 0; + } + /* cluster{} moved to remove_xline */ + + remove_xline(source_p, parv[1], propagated); return 0; } @@ -434,13 +474,13 @@ handle_remote_unxline(struct Client *source_p, const char *name) source_p->servptr->name, SHARED_UNXLINE)) return; - remove_xline(source_p, name); + remove_xline(source_p, name, 0); return; } static void -remove_xline(struct Client *source_p, const char *name) +remove_xline(struct Client *source_p, const char *name, int propagated) { struct ConfItem *aconf; rb_dlink_node *ptr; @@ -451,6 +491,41 @@ remove_xline(struct Client *source_p, const char *name) if(!irccmp(aconf->host, name)) { + if(aconf->lifetime) + { + if(!propagated) + { + sendto_one_notice(source_p, ":Cannot remove global X-Line %s on specific servers", name); + return; + } + ptr = rb_dlinkFind(aconf, &prop_bans); + if(ptr == NULL) + return; + sendto_one_notice(source_p, ":X-Line for [%s] is removed", name); + sendto_realops_snomask(SNO_GENERAL, L_ALL, + "%s has removed the global X-Line for: [%s]", + get_oper_name(source_p), name); + ilog(L_KLINE, "UX %s %s", get_oper_name(source_p), name); + if(aconf->created < rb_current_time()) + aconf->created = rb_current_time(); + else + aconf->created++; + aconf->hold = aconf->created; + operhash_delete(aconf->info.oper); + aconf->info.oper = operhash_add(get_oper_name(source_p)); + aconf->flags |= CONF_FLAGS_MYOPER | CONF_FLAGS_TEMPORARY; + sendto_server(NULL, NULL, CAP_BAN|CAP_TS6, NOCAPS, + ":%s BAN X * %s %lu %d %d * :*", + source_p->id, aconf->host, + (unsigned long)aconf->created, + 0, + (int)(aconf->lifetime - aconf->created)); + remove_reject_mask(aconf->host, NULL); + deactivate_conf(aconf, ptr); + return; + } + else if(MyClient(source_p) && rb_dlink_list_length(&cluster_conf_list)) + cluster_generic(source_p, "UNXLINE", SHARED_UNXLINE, CAP_CLUSTER, "%s", name); if(!aconf->hold) { bandb_del(BANDB_XLINE, aconf->host, NULL); @@ -477,6 +552,9 @@ remove_xline(struct Client *source_p, const char *name) } } + if(MyClient(source_p) && rb_dlink_list_length(&cluster_conf_list)) + cluster_generic(source_p, "UNXLINE", SHARED_UNXLINE, CAP_CLUSTER, "%s", name); + sendto_one_notice(source_p, ":No X-Line for %s", name); return; diff --git a/src/s_conf.c b/src/s_conf.c index 3f46088..768ae2f 100644 --- a/src/s_conf.c +++ b/src/s_conf.c @@ -1133,6 +1133,36 @@ deactivate_conf(struct ConfItem *aconf, rb_dlink_node *ptr) } } +/* Given a new ban ConfItem, look for any matching ban, update the lifetime + * from it and delete it. + */ +void +replace_old_ban(struct ConfItem *aconf) +{ + rb_dlink_node *ptr; + struct ConfItem *oldconf; + + ptr = find_prop_ban(aconf->status, aconf->user, aconf->host); + if(ptr != NULL) + { + oldconf = ptr->data; + /* Remember at least as long as the old one. */ + if(oldconf->lifetime > aconf->lifetime) + aconf->lifetime = oldconf->lifetime; + /* Force creation time to increase. */ + if(oldconf->created >= aconf->created) + aconf->created = oldconf->created + 1; + /* Leave at least one second of validity. */ + if(aconf->hold <= aconf->created) + aconf->hold = aconf->created + 1; + if(aconf->lifetime < aconf->hold) + aconf->lifetime = aconf->hold; + /* Tell deactivate_conf() to destroy it. */ + oldconf->lifetime = rb_current_time(); + deactivate_conf(oldconf, ptr); + } +} + static void expire_prop_bans(void *list) { From a75522e6a5663d0a29345528e55dadee652df2d5 Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Thu, 18 Mar 2010 00:22:35 +0100 Subject: [PATCH 27/32] BAN: xlines do not have oper reasons, their "reason" is already oper only. --- modules/core/m_ban.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/core/m_ban.c b/modules/core/m_ban.c index 0efe6ef..1fecd3f 100644 --- a/modules/core/m_ban.c +++ b/modules/core/m_ban.c @@ -157,8 +157,7 @@ ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *p aconf->info.oper = operhash_add(oper); aconf->created = created; aconf->hold = hold; - p = strchr(parv[parc - 1], '|'); - if (p == NULL) + if (ntype != CONF_KILL || (p = strchr(parv[parc - 1], '|')) == NULL) aconf->passwd = rb_strdup(parv[parc - 1]); else { From 5d2661a14983622ed7a8e9cc7ef8c55a3d0879ad Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Sat, 27 Mar 2010 02:06:29 +0100 Subject: [PATCH 28/32] Remove unused variable. --- modules/m_xline.c | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/m_xline.c b/modules/m_xline.c index 566a369..315a686 100644 --- a/modules/m_xline.c +++ b/modules/m_xline.c @@ -283,7 +283,6 @@ valid_xline(struct Client *source_p, const char *gecos, const char *reason) void apply_xline(struct Client *source_p, const char *name, const char *reason, int temp_time, int propagated) { - rb_dlink_node *ptr; struct ConfItem *aconf; aconf = make_conf(); From d0cf872a952a8212ea7a7b44ddbb1b4a590f0524 Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Sat, 27 Mar 2010 16:09:26 +0100 Subject: [PATCH 29/32] XLINE: Do not cluster unxlines ON specific servers. This bug was introduced with BAN support for XLINE. --- modules/m_xline.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/m_xline.c b/modules/m_xline.c index 315a686..d1975ec 100644 --- a/modules/m_xline.c +++ b/modules/m_xline.c @@ -523,7 +523,7 @@ remove_xline(struct Client *source_p, const char *name, int propagated) deactivate_conf(aconf, ptr); return; } - else if(MyClient(source_p) && rb_dlink_list_length(&cluster_conf_list)) + else if(propagated && rb_dlink_list_length(&cluster_conf_list)) cluster_generic(source_p, "UNXLINE", SHARED_UNXLINE, CAP_CLUSTER, "%s", name); if(!aconf->hold) { @@ -551,7 +551,7 @@ remove_xline(struct Client *source_p, const char *name, int propagated) } } - if(MyClient(source_p) && rb_dlink_list_length(&cluster_conf_list)) + if(propagated && rb_dlink_list_length(&cluster_conf_list)) cluster_generic(source_p, "UNXLINE", SHARED_UNXLINE, CAP_CLUSTER, "%s", name); sendto_one_notice(source_p, ":No X-Line for %s", name); From 9b9d818b321d02faff8aa3a778c7402157bc6f77 Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Sat, 27 Mar 2010 16:13:57 +0100 Subject: [PATCH 30/32] Add propagated resvs, like klines and xlines. --- doc/reference.conf | 2 +- help/opers/stats | 2 +- include/channel.h | 2 + modules/core/m_ban.c | 35 ++++++- modules/m_resv.c | 228 ++++++++++++++++++++++++++++++------------- src/channel.c | 51 ++++++++++ 6 files changed, 245 insertions(+), 75 deletions(-) diff --git a/doc/reference.conf b/doc/reference.conf index c46ffa8..b915dfc 100755 --- a/doc/reference.conf +++ b/doc/reference.conf @@ -1198,7 +1198,7 @@ general { */ warn_no_nline = yes; - /* use propagated bans: KLINE and XLINE set fully propagated bans. + /* use propagated bans: KLINE, XLINE and RESV set fully propagated bans. * That means the bans are part of the netburst and restarted/split * servers will get them, but they will not apply to 3.2 and older * servers at all. diff --git a/help/opers/stats b/help/opers/stats index f20ad56..fb7bb34 100644 --- a/help/opers/stats +++ b/help/opers/stats @@ -29,7 +29,7 @@ X f - Shows File Descriptors ^ o - Shows operator blocks (Old O: lines) ^ P - Shows configured ports p - Shows online opers -* q - Shows temporary resv'd nicks and channels +* q - Shows temporary and global resv'd nicks and channels * Q - Shows resv'd nicks and channels * r - Shows resource usage by ircd * t - Shows generic server stats diff --git a/include/channel.h b/include/channel.h index 6a0a56a..cc8a18c 100644 --- a/include/channel.h +++ b/include/channel.h @@ -277,6 +277,8 @@ extern void unset_chcap_usage_counts(struct Client *serv_p); extern void send_cap_mode_changes(struct Client *client_p, struct Client *source_p, struct Channel *chptr, struct ChModeChange foo[], int); +void resv_chan_forcepart(const char *name, const char *reason, int temp_time); + extern void set_channel_mode(struct Client *client_p, struct Client *source_p, struct Channel *chptr, struct membership *msptr, int parc, const char *parv[]); diff --git a/modules/core/m_ban.c b/modules/core/m_ban.c index 1fecd3f..8481282 100644 --- a/modules/core/m_ban.c +++ b/modules/core/m_ban.c @@ -29,6 +29,7 @@ #include "stdinc.h" #include "send.h" +#include "channel.h" #include "client.h" #include "common.h" #include "config.h" @@ -75,6 +76,7 @@ ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *p time_t created, hold, lifetime; char *p; int act; + int valid; if (strlen(parv[1]) != 1) { @@ -93,6 +95,11 @@ ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *p ntype = CONF_XLINE; stype = "X-Line"; break; + case 'R': + ntype = IsChannelName(parv[3]) ? CONF_RESV_CHANNEL : + CONF_RESV_NICK; + stype = "RESV"; + break; default: sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "Unknown BAN type %s from %s", @@ -164,10 +171,19 @@ ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *p aconf->passwd = rb_strndup(parv[parc - 1], p - parv[parc - 1] + 1); aconf->spasswd = rb_strdup(p + 1); } - if (act && hold != created && - !(ntype == CONF_KILL ? - valid_wild_card(aconf->user, aconf->host) : - valid_wild_card_simple(aconf->host))) + switch (ntype) + { + case CONF_KILL: + valid = valid_wild_card(aconf->user, aconf->host); + break; + case CONF_RESV_CHANNEL: + valid = 1; + break; + default: + valid = valid_wild_card_simple(aconf->host); + break; + } + if (act && hold != created && !valid) { sendto_realops_snomask(SNO_GENERAL, L_ALL, "Ignoring global %d min. %s from %s%s%s for [%s%s%s]: too few non-wildcard characters", @@ -260,6 +276,17 @@ ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *p check_xlines(); } break; + case CONF_RESV_CHANNEL: + if (!(aconf->status & CONF_ILLEGAL)) + { + add_to_resv_hash(aconf->host, aconf); + resv_chan_forcepart(aconf->host, aconf->passwd, hold - rb_current_time()); + } + break; + case CONF_RESV_NICK: + if (!(aconf->status & CONF_ILLEGAL)) + rb_dlinkAddAlloc(aconf, &resv_conf_list); + break; } sendto_server(client_p, NULL, CAP_BAN|CAP_TS6, NOCAPS, ":%s BAN %s %s %s %s %s %s %s :%s", diff --git a/modules/m_resv.c b/modules/m_resv.c index 01b41b7..cdcaecb 100644 --- a/modules/m_resv.c +++ b/modules/m_resv.c @@ -62,15 +62,14 @@ mapi_clist_av1 resv_clist[] = { &resv_msgtab, &unresv_msgtab, NULL }; DECLARE_MODULE_AV1(resv, NULL, NULL, resv_clist, NULL, NULL, "$Revision$"); static void parse_resv(struct Client *source_p, const char *name, - const char *reason, int temp_time); + const char *reason, int temp_time, int propagated); static void propagate_resv(struct Client *source_p, const char *target, int temp_time, const char *name, const char *reason); static void cluster_resv(struct Client *source_p, int temp_time, const char *name, const char *reason); static void handle_remote_unresv(struct Client *source_p, const char *name); -static void remove_resv(struct Client *source_p, const char *name); -static void resv_chan_forcepart(const char *name, const char *reason, int temp_time); +static void remove_resv(struct Client *source_p, const char *name, int propagated); /* * mo_resv() @@ -86,6 +85,7 @@ mo_resv(struct Client *client_p, struct Client *source_p, int parc, const char * const char *target_server = NULL; int temp_time; int loc = 1; + int propagated = ConfigFileEntry.use_propagated_bans; if(!IsOperResv(source_p)) { @@ -115,6 +115,9 @@ mo_resv(struct Client *client_p, struct Client *source_p, int parc, const char * target_server = parv[loc + 1]; loc += 2; + + /* Set as local-only. */ + propagated = 0; } if(parc <= loc || EmptyString(parv[loc])) @@ -133,10 +136,16 @@ mo_resv(struct Client *client_p, struct Client *source_p, int parc, const char * if(match(target_server, me.name) == 0) return 0; } - else if(rb_dlink_list_length(&cluster_conf_list) > 0) + else if(!propagated && rb_dlink_list_length(&cluster_conf_list) > 0) cluster_resv(source_p, temp_time, name, reason); - parse_resv(source_p, name, reason, temp_time); + if(propagated && temp_time == 0) + { + sendto_one_notice(source_p, ":Cannot set a permanent global ban"); + return 0; + } + + parse_resv(source_p, name, reason, temp_time, propagated); return 0; } @@ -161,7 +170,7 @@ ms_resv(struct Client *client_p, struct Client *source_p, int parc, const char * if(!IsPerson(source_p)) return 0; - parse_resv(source_p, parv[2], parv[3], 0); + parse_resv(source_p, parv[2], parv[3], 0, 0); return 0; } @@ -172,7 +181,7 @@ me_resv(struct Client *client_p, struct Client *source_p, int parc, const char * if(!IsPerson(source_p)) return 0; - parse_resv(source_p, parv[2], parv[4], atoi(parv[1])); + parse_resv(source_p, parv[2], parv[4], atoi(parv[1]), 0); return 0; } @@ -185,7 +194,7 @@ me_resv(struct Client *client_p, struct Client *source_p, int parc, const char * * side effects - will parse the resv and create it if valid */ static void -parse_resv(struct Client *source_p, const char *name, const char *reason, int temp_time) +parse_resv(struct Client *source_p, const char *name, const char *reason, int temp_time, int propagated) { struct ConfItem *aconf; @@ -223,10 +232,32 @@ parse_resv(struct Client *source_p, const char *name, const char *reason, int te aconf->host = rb_strdup(name); aconf->passwd = rb_strdup(reason); aconf->info.oper = operhash_add(get_oper_name(source_p)); - add_to_resv_hash(aconf->host, aconf); - resv_chan_forcepart(aconf->host, aconf->passwd, temp_time); - if(temp_time > 0) + if(propagated) + { + aconf->flags |= CONF_FLAGS_MYOPER | CONF_FLAGS_TEMPORARY; + aconf->hold = rb_current_time() + temp_time; + aconf->lifetime = aconf->hold; + replace_old_ban(aconf); + rb_dlinkAddAlloc(aconf, &prop_bans); + + sendto_realops_snomask(SNO_GENERAL, L_ALL, + "%s added global %d min. RESV for [%s] [%s]", + get_oper_name(source_p), temp_time / 60, + name, reason); + ilog(L_KLINE, "R %s %d %s %s", + get_oper_name(source_p), temp_time / 60, name, reason); + sendto_one_notice(source_p, ":Added global %d min. RESV [%s]", + temp_time / 60, name); + sendto_server(NULL, NULL, CAP_BAN|CAP_TS6, NOCAPS, + ":%s BAN R * %s %lu %d %d * :%s", + source_p->id, aconf->host, + (unsigned long)aconf->created, + (int)(aconf->hold - aconf->created), + (int)(aconf->lifetime - aconf->created), + reason); + } + else if(temp_time > 0) { aconf->hold = rb_current_time() + temp_time; @@ -250,6 +281,9 @@ parse_resv(struct Client *source_p, const char *name, const char *reason, int te bandb_add(BANDB_RESV, source_p, aconf->host, NULL, aconf->passwd, NULL, 0); } + + add_to_resv_hash(aconf->host, aconf); + resv_chan_forcepart(aconf->host, aconf->passwd, temp_time); } else if(clean_resv_nick(name)) { @@ -288,9 +322,32 @@ parse_resv(struct Client *source_p, const char *name, const char *reason, int te aconf->host = rb_strdup(name); aconf->passwd = rb_strdup(reason); aconf->info.oper = operhash_add(get_oper_name(source_p)); - rb_dlinkAddAlloc(aconf, &resv_conf_list); - if(temp_time > 0) + if(propagated) + { + aconf->flags |= CONF_FLAGS_MYOPER | CONF_FLAGS_TEMPORARY; + aconf->hold = rb_current_time() + temp_time; + aconf->lifetime = aconf->hold; + replace_old_ban(aconf); + rb_dlinkAddAlloc(aconf, &prop_bans); + + sendto_realops_snomask(SNO_GENERAL, L_ALL, + "%s added global %d min. RESV for [%s] [%s]", + get_oper_name(source_p), temp_time / 60, + name, reason); + ilog(L_KLINE, "R %s %d %s %s", + get_oper_name(source_p), temp_time / 60, name, reason); + sendto_one_notice(source_p, ":Added global %d min. RESV [%s]", + temp_time / 60, name); + sendto_server(NULL, NULL, CAP_BAN|CAP_TS6, NOCAPS, + ":%s BAN R * %s %lu %d %d * :%s", + source_p->id, aconf->host, + (unsigned long)aconf->created, + (int)(aconf->hold - aconf->created), + (int)(aconf->lifetime - aconf->created), + reason); + } + else if(temp_time > 0) { aconf->hold = rb_current_time() + temp_time; @@ -314,6 +371,8 @@ parse_resv(struct Client *source_p, const char *name, const char *reason, int te bandb_add(BANDB_RESV, source_p, aconf->host, NULL, aconf->passwd, NULL, 0); } + + rb_dlinkAddAlloc(aconf, &resv_conf_list); } else sendto_one_notice(source_p, ":You have specified an invalid resv: [%s]", name); @@ -380,6 +439,8 @@ cluster_resv(struct Client *source_p, int temp_time, const char *name, const cha static int mo_unresv(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { + int propagated = 1; + if(!IsOperResv(source_p)) { sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name, "resv"); @@ -399,11 +460,16 @@ mo_unresv(struct Client *client_p, struct Client *source_p, int parc, const char if(match(parv[3], me.name) == 0) return 0; + + propagated = 0; } +#if 0 else if(rb_dlink_list_length(&cluster_conf_list) > 0) cluster_generic(source_p, "UNRESV", SHARED_UNRESV, CAP_CLUSTER, "%s", parv[1]); +#endif + /* cluster{} moved to remove_resv */ - remove_resv(source_p, parv[1]); + remove_resv(source_p, parv[1], propagated); return 0; } @@ -448,24 +514,63 @@ handle_remote_unresv(struct Client *source_p, const char *name) source_p->servptr->name, SHARED_UNRESV)) return; - remove_resv(source_p, name); + remove_resv(source_p, name, 0); return; } static void -remove_resv(struct Client *source_p, const char *name) +remove_resv(struct Client *source_p, const char *name, int propagated) { struct ConfItem *aconf = NULL; + rb_dlink_node *ptr; if(IsChannelName(name)) { if((aconf = hash_find_resv(name)) == NULL) { + if(propagated && rb_dlink_list_length(&cluster_conf_list)) + cluster_generic(source_p, "UNXLINE", SHARED_UNXLINE, CAP_CLUSTER, "%s", name); + sendto_one_notice(source_p, ":No RESV for %s", name); return; } + if(aconf->lifetime) + { + if(!propagated) + { + sendto_one_notice(source_p, ":Cannot remove global RESV %s on specific servers", name); + return; + } + ptr = rb_dlinkFind(aconf, &prop_bans); + if(ptr == NULL) + return; + sendto_one_notice(source_p, ":RESV for [%s] is removed", name); + sendto_realops_snomask(SNO_GENERAL, L_ALL, + "%s has removed the global RESV for: [%s]", + get_oper_name(source_p), name); + ilog(L_KLINE, "UR %s %s", get_oper_name(source_p), name); + if(aconf->created < rb_current_time()) + aconf->created = rb_current_time(); + else + aconf->created++; + aconf->hold = aconf->created; + operhash_delete(aconf->info.oper); + aconf->info.oper = operhash_add(get_oper_name(source_p)); + aconf->flags |= CONF_FLAGS_MYOPER | CONF_FLAGS_TEMPORARY; + sendto_server(NULL, NULL, CAP_BAN|CAP_TS6, NOCAPS, + ":%s BAN R * %s %lu %d %d * :*", + source_p->id, aconf->host, + (unsigned long)aconf->created, + 0, + (int)(aconf->lifetime - aconf->created)); + deactivate_conf(aconf, ptr); + return; + } + else if(propagated && rb_dlink_list_length(&cluster_conf_list) > 0) + cluster_generic(source_p, "UNRESV", SHARED_UNRESV, CAP_CLUSTER, "%s", name); + sendto_one_notice(source_p, ":RESV for [%s] is removed", name); ilog(L_KLINE, "UR %s %s", get_oper_name(source_p), name); if(!aconf->hold) @@ -485,8 +590,6 @@ remove_resv(struct Client *source_p, const char *name) } else { - rb_dlink_node *ptr; - RB_DLINK_FOREACH(ptr, resv_conf_list.head) { aconf = ptr->data; @@ -499,10 +602,48 @@ remove_resv(struct Client *source_p, const char *name) if(aconf == NULL) { + if(propagated && rb_dlink_list_length(&cluster_conf_list)) + cluster_generic(source_p, "UNXLINE", SHARED_UNXLINE, CAP_CLUSTER, "%s", name); + sendto_one_notice(source_p, ":No RESV for %s", name); return; } + if(aconf->lifetime) + { + if(!propagated) + { + sendto_one_notice(source_p, ":Cannot remove global RESV %s on specific servers", name); + return; + } + ptr = rb_dlinkFind(aconf, &prop_bans); + if(ptr == NULL) + return; + sendto_one_notice(source_p, ":RESV for [%s] is removed", name); + sendto_realops_snomask(SNO_GENERAL, L_ALL, + "%s has removed the global RESV for: [%s]", + get_oper_name(source_p), name); + ilog(L_KLINE, "UR %s %s", get_oper_name(source_p), name); + if(aconf->created < rb_current_time()) + aconf->created = rb_current_time(); + else + aconf->created++; + aconf->hold = aconf->created; + operhash_delete(aconf->info.oper); + aconf->info.oper = operhash_add(get_oper_name(source_p)); + aconf->flags |= CONF_FLAGS_MYOPER | CONF_FLAGS_TEMPORARY; + sendto_server(NULL, NULL, CAP_BAN|CAP_TS6, NOCAPS, + ":%s BAN R * %s %lu %d %d * :*", + source_p->id, aconf->host, + (unsigned long)aconf->created, + 0, + (int)(aconf->lifetime - aconf->created)); + deactivate_conf(aconf, ptr); + return; + } + else if(propagated && rb_dlink_list_length(&cluster_conf_list) > 0) + cluster_generic(source_p, "UNRESV", SHARED_UNRESV, CAP_CLUSTER, "%s", name); + if(!aconf->hold) bandb_del(BANDB_RESV, aconf->host, NULL); else @@ -520,54 +661,3 @@ remove_resv(struct Client *source_p, const char *name) return; } - -static void -resv_chan_forcepart(const char *name, const char *reason, int temp_time) -{ - rb_dlink_node *ptr; - rb_dlink_node *next_ptr; - struct Channel *chptr; - struct membership *msptr; - struct Client *target_p; - - if(!ConfigChannel.resv_forcepart) - return; - - /* for each user on our server in the channel list - * send them a PART, and notify opers. - */ - chptr = find_channel(name); - if(chptr != NULL) - { - RB_DLINK_FOREACH_SAFE(ptr, next_ptr, chptr->locmembers.head) - { - msptr = ptr->data; - target_p = msptr->client_p; - - if(IsExemptResv(target_p)) - continue; - - sendto_server(target_p, chptr, CAP_TS6, NOCAPS, - ":%s PART %s", target_p->id, chptr->chname); - - sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s PART %s :%s", - target_p->name, target_p->username, - target_p->host, chptr->chname, target_p->name); - - remove_user_from_channel(msptr); - - /* notify opers & user they were removed from the channel */ - sendto_realops_snomask(SNO_GENERAL, L_ALL, - "Forced PART for %s!%s@%s from %s (%s)", - target_p->name, target_p->username, - target_p->host, name, reason); - - if(temp_time > 0) - sendto_one_notice(target_p, ":*** Channel %s is temporarily unavailable on this server.", - name); - else - sendto_one_notice(target_p, ":*** Channel %s is no longer available on this server.", - name); - } - } -} diff --git a/src/channel.c b/src/channel.c index 52f5b2b..74767f4 100644 --- a/src/channel.c +++ b/src/channel.c @@ -1532,6 +1532,57 @@ send_cap_mode_changes(struct Client *client_p, struct Client *source_p, } } +void +resv_chan_forcepart(const char *name, const char *reason, int temp_time) +{ + rb_dlink_node *ptr; + rb_dlink_node *next_ptr; + struct Channel *chptr; + struct membership *msptr; + struct Client *target_p; + + if(!ConfigChannel.resv_forcepart) + return; + + /* for each user on our server in the channel list + * send them a PART, and notify opers. + */ + chptr = find_channel(name); + if(chptr != NULL) + { + RB_DLINK_FOREACH_SAFE(ptr, next_ptr, chptr->locmembers.head) + { + msptr = ptr->data; + target_p = msptr->client_p; + + if(IsExemptResv(target_p)) + continue; + + sendto_server(target_p, chptr, CAP_TS6, NOCAPS, + ":%s PART %s", target_p->id, chptr->chname); + + sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s PART %s :%s", + target_p->name, target_p->username, + target_p->host, chptr->chname, target_p->name); + + remove_user_from_channel(msptr); + + /* notify opers & user they were removed from the channel */ + sendto_realops_snomask(SNO_GENERAL, L_ALL, + "Forced PART for %s!%s@%s from %s (%s)", + target_p->name, target_p->username, + target_p->host, name, reason); + + if(temp_time > 0) + sendto_one_notice(target_p, ":*** Channel %s is temporarily unavailable on this server.", + name); + else + sendto_one_notice(target_p, ":*** Channel %s is no longer available on this server.", + name); + } + } +} + /* Check what we will forward to, without sending any notices to the user * -- jilles */ From 7bf8ae67ccbcb94a11bf0bf0b57108a3a2ac3b9c Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Sat, 27 Mar 2010 16:24:13 +0100 Subject: [PATCH 31/32] Restore snotes, logs for UNRESV nick. This bug was introduced when adding bandb. --- modules/m_resv.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/modules/m_resv.c b/modules/m_resv.c index cdcaecb..af72747 100644 --- a/modules/m_resv.c +++ b/modules/m_resv.c @@ -644,15 +644,20 @@ remove_resv(struct Client *source_p, const char *name, int propagated) else if(propagated && rb_dlink_list_length(&cluster_conf_list) > 0) cluster_generic(source_p, "UNRESV", SHARED_UNRESV, CAP_CLUSTER, "%s", name); + sendto_one_notice(source_p, ":RESV for [%s] is removed", name); + ilog(L_KLINE, "UR %s %s", get_oper_name(source_p), name); if(!aconf->hold) - bandb_del(BANDB_RESV, aconf->host, NULL); - else { - sendto_one_notice(source_p, ":RESV for [%s] is removed", name); + bandb_del(BANDB_RESV, aconf->host, NULL); sendto_realops_snomask(SNO_GENERAL, L_ALL, "%s has removed the RESV for: [%s]", get_oper_name(source_p), name); - ilog(L_KLINE, "UR %s %s", get_oper_name(source_p), name); + } + else + { + sendto_realops_snomask(SNO_GENERAL, L_ALL, + "%s has removed the temporary RESV for: [%s]", + get_oper_name(source_p), name); } /* already have ptr from the loop above.. */ rb_dlinkDestroy(ptr, &resv_conf_list); From 7c880acbfebf4e08ba4009c8708616fe6ff21ba0 Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Sat, 27 Mar 2010 20:09:46 +0100 Subject: [PATCH 32/32] Fix various compiler warnings. --- modules/core/m_ban.c | 6 +++--- modules/m_kline.c | 2 +- src/s_conf.c | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/core/m_ban.c b/modules/core/m_ban.c index 8481282..d966edd 100644 --- a/modules/core/m_ban.c +++ b/modules/core/m_ban.c @@ -187,7 +187,7 @@ ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *p { sendto_realops_snomask(SNO_GENERAL, L_ALL, "Ignoring global %d min. %s from %s%s%s for [%s%s%s]: too few non-wildcard characters", - (hold - rb_current_time()) / 60, + (int)((hold - rb_current_time()) / 60), stype, IsServer(source_p) ? source_p->name : get_oper_name(source_p), strcmp(parv[7], "*") ? " on behalf of " : "", @@ -210,7 +210,7 @@ ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *p sendto_realops_snomask(SNO_GENERAL, L_ALL, "%s added global %d min. %s%s%s for [%s%s%s] [%s]", IsServer(source_p) ? source_p->name : get_oper_name(source_p), - (hold - rb_current_time()) / 60, + (int)((hold - rb_current_time()) / 60), stype, strcmp(parv[7], "*") ? " from " : "", strcmp(parv[7], "*") ? parv[7] : "", @@ -220,7 +220,7 @@ ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *p parv[parc - 1]); ilog(L_KLINE, "%s %s %d %s%s%s %s", parv[1], IsServer(source_p) ? source_p->name : get_oper_name(source_p), - (hold - rb_current_time()) / 60, + (int)((hold - rb_current_time()) / 60), aconf->user ? aconf->user : "", aconf->user ? " " : "", aconf->host, diff --git a/modules/m_kline.c b/modules/m_kline.c index d6e22bc..89ba235 100644 --- a/modules/m_kline.c +++ b/modules/m_kline.c @@ -297,7 +297,7 @@ handle_remote_kline(struct Client *source_p, int tkline_time, ":Please include at least %d non-wildcard " "characters with the user@host", ConfigFileEntry.min_nonwildcard); - return 0; + return; } if(already_placed_kline(source_p, user, host, tkline_time)) diff --git a/src/s_conf.c b/src/s_conf.c index 768ae2f..5f91e6c 100644 --- a/src/s_conf.c +++ b/src/s_conf.c @@ -1330,7 +1330,7 @@ get_user_ban_reason(struct ConfItem *aconf) rb_snprintf(reasonbuf, sizeof reasonbuf, "Temporary %c-line %d min. - ", aconf->status == CONF_DLINE ? 'D' : 'K', - (aconf->hold - aconf->created) / 60); + (int)((aconf->hold - aconf->created) / 60)); else reasonbuf[0] = '\0'; if (aconf->passwd)