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.
This commit is contained in:
parent
90072e8be6
commit
65b8e0029e
|
@ -97,6 +97,7 @@ struct ConfItem
|
||||||
/* Generic flags... */
|
/* Generic flags... */
|
||||||
#define CONF_FLAGS_TEMPORARY 0x00800000
|
#define CONF_FLAGS_TEMPORARY 0x00800000
|
||||||
#define CONF_FLAGS_NEED_SSL 0x00000002
|
#define CONF_FLAGS_NEED_SSL 0x00000002
|
||||||
|
#define CONF_FLAGS_MYOPER 0x00080000 /* need to rewrite info.oper on burst */
|
||||||
/* auth{} flags... */
|
/* auth{} flags... */
|
||||||
#define CONF_FLAGS_NO_TILDE 0x00000004
|
#define CONF_FLAGS_NO_TILDE 0x00000004
|
||||||
#define CONF_FLAGS_NEED_IDENTD 0x00000008
|
#define CONF_FLAGS_NEED_IDENTD 0x00000008
|
||||||
|
@ -347,6 +348,7 @@ extern void init_s_conf(void);
|
||||||
extern struct ConfItem *make_conf(void);
|
extern struct ConfItem *make_conf(void);
|
||||||
extern void free_conf(struct ConfItem *);
|
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 deactivate_conf(struct ConfItem *, rb_dlink_node *);
|
||||||
|
|
||||||
extern void read_conf_files(int cold);
|
extern void read_conf_files(int cold);
|
||||||
|
|
|
@ -72,12 +72,14 @@ struct Capability
|
||||||
#define CAP_SAVE 0x40000 /* supports SAVE (nick collision FNC) */
|
#define CAP_SAVE 0x40000 /* supports SAVE (nick collision FNC) */
|
||||||
#define CAP_EUID 0x80000 /* supports EUID (ext UID + nonencap CHGHOST) */
|
#define CAP_EUID 0x80000 /* supports EUID (ext UID + nonencap CHGHOST) */
|
||||||
#define CAP_EOPMOD 0x100000 /* supports EOPMOD (ext +z + ext topic) */
|
#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 | \
|
#define CAP_MASK (CAP_QS | CAP_EX | CAP_CHW | \
|
||||||
CAP_IE | CAP_KLN | CAP_SERVICE |\
|
CAP_IE | CAP_KLN | CAP_SERVICE |\
|
||||||
CAP_CLUSTER | CAP_ENCAP | \
|
CAP_CLUSTER | CAP_ENCAP | \
|
||||||
CAP_ZIP | CAP_KNOCK | CAP_UNKLN | \
|
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
|
#ifdef HAVE_LIBZ
|
||||||
#define CAP_ZIP_SUPPORTED CAP_ZIP
|
#define CAP_ZIP_SUPPORTED CAP_ZIP
|
||||||
|
|
|
@ -36,6 +36,7 @@ INCLUDES = -I../include -I../libratbox/include $(SSL_INCLUDES)
|
||||||
CPPFLAGS = ${INCLUDES} @CPPFLAGS@
|
CPPFLAGS = ${INCLUDES} @CPPFLAGS@
|
||||||
|
|
||||||
CORE_SRCS = \
|
CORE_SRCS = \
|
||||||
|
core/m_ban.c \
|
||||||
core/m_die.c \
|
core/m_die.c \
|
||||||
core/m_error.c \
|
core/m_error.c \
|
||||||
core/m_join.c \
|
core/m_join.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;
|
||||||
|
}
|
|
@ -79,11 +79,14 @@ static void apply_kline(struct Client *source_p, struct ConfItem *aconf,
|
||||||
const char *reason, const char *oper_reason);
|
const char *reason, const char *oper_reason);
|
||||||
static void apply_tkline(struct Client *source_p, struct ConfItem *aconf,
|
static void apply_tkline(struct Client *source_p, struct ConfItem *aconf,
|
||||||
const char *, const char *, int);
|
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 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 handle_remote_unkline(struct Client *source_p, const char *user, const char *host);
|
||||||
static void remove_permkline_match(struct Client *, struct ConfItem *);
|
static void remove_permkline_match(struct Client *, struct ConfItem *);
|
||||||
static int remove_temp_kline(struct Client *, struct ConfItem *);
|
static int remove_temp_kline(struct Client *, struct ConfItem *);
|
||||||
|
static void remove_prop_kline(struct Client *, struct ConfItem *);
|
||||||
|
|
||||||
/* mo_kline()
|
/* mo_kline()
|
||||||
*
|
*
|
||||||
|
@ -105,6 +108,7 @@ mo_kline(struct Client *client_p, struct Client *source_p, int parc, const char
|
||||||
struct ConfItem *aconf;
|
struct ConfItem *aconf;
|
||||||
int tkline_time = 0;
|
int tkline_time = 0;
|
||||||
int loc = 1;
|
int loc = 1;
|
||||||
|
int propagated = 1;
|
||||||
|
|
||||||
if(!IsOperK(source_p))
|
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 we are sending it somewhere that doesnt include us, stop */
|
||||||
if(!match(target_server, me.name))
|
if(!match(target_server, me.name))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
/* Set as local-only. */
|
||||||
|
propagated = 0;
|
||||||
}
|
}
|
||||||
/* if we have cluster servers, send it to them.. */
|
/* 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",
|
cluster_generic(source_p, "KLINE",
|
||||||
(tkline_time > 0) ? SHARED_TKLINE : SHARED_PKLINE, CAP_KLN,
|
(tkline_time > 0) ? SHARED_TKLINE : SHARED_PKLINE, CAP_KLN,
|
||||||
"%lu %s %s :%s", tkline_time, user, host, reason);
|
"%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))
|
!valid_wild_card(source_p, user, host) || !valid_comment(source_p, reason))
|
||||||
return 0;
|
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))
|
if(already_placed_kline(source_p, user, host, tkline_time))
|
||||||
return 0;
|
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);
|
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);
|
apply_tkline(source_p, aconf, reason, oper_reason, tkline_time);
|
||||||
else
|
else
|
||||||
apply_kline(source_p, aconf, reason, oper_reason);
|
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 splat[] = "*";
|
||||||
char *h = LOCAL_COPY(parv[1]);
|
char *h = LOCAL_COPY(parv[1]);
|
||||||
struct ConfItem *aconf;
|
struct ConfItem *aconf;
|
||||||
|
int propagated = 1;
|
||||||
|
|
||||||
if(!IsOperUnkline(source_p))
|
if(!IsOperUnkline(source_p))
|
||||||
{
|
{
|
||||||
|
@ -375,18 +391,33 @@ mo_unkline(struct Client *client_p, struct Client *source_p, int parc, const cha
|
||||||
|
|
||||||
if(match(parv[3], me.name) == 0)
|
if(match(parv[3], me.name) == 0)
|
||||||
return 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,
|
cluster_generic(source_p, "UNKLINE", SHARED_UNKLINE, CAP_UNKLN,
|
||||||
"%s %s", user, host);
|
"%s %s", user, host);
|
||||||
|
|
||||||
aconf = find_exact_conf_by_address(host, CONF_KILL, user);
|
|
||||||
if(aconf == NULL)
|
if(aconf == NULL)
|
||||||
{
|
{
|
||||||
sendto_one_notice(source_p, ":No K-Line for %s@%s", user, host);
|
sendto_one_notice(source_p, ":No K-Line for %s@%s", user, host);
|
||||||
return 0;
|
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))
|
if(remove_temp_kline(source_p, aconf))
|
||||||
return 0;
|
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);
|
sendto_one_notice(source_p, ":No K-Line for %s@%s", user, host);
|
||||||
return;
|
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))
|
if(remove_temp_kline(source_p, aconf))
|
||||||
return;
|
return;
|
||||||
|
@ -527,6 +563,70 @@ apply_tkline(struct Client *source_p, struct ConfItem *aconf,
|
||||||
tkline_time / 60, aconf->user, aconf->host);
|
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()
|
/* find_user_host()
|
||||||
*
|
*
|
||||||
* inputs - client placing kline, user@host, user buffer, host buffer
|
* 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;
|
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);
|
||||||
|
}
|
||||||
|
|
|
@ -58,6 +58,7 @@
|
||||||
struct module **modlist = NULL;
|
struct module **modlist = NULL;
|
||||||
|
|
||||||
static const char *core_module_table[] = {
|
static const char *core_module_table[] = {
|
||||||
|
"m_ban",
|
||||||
"m_die",
|
"m_die",
|
||||||
"m_error",
|
"m_error",
|
||||||
"m_join",
|
"m_join",
|
||||||
|
|
19
src/s_conf.c
19
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);
|
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
|
void
|
||||||
deactivate_conf(struct ConfItem *aconf, rb_dlink_node *ptr)
|
deactivate_conf(struct ConfItem *aconf, rb_dlink_node *ptr)
|
||||||
{
|
{
|
||||||
|
|
65
src/s_serv.c
65
src/s_serv.c
|
@ -89,6 +89,7 @@ struct Capability captab[] = {
|
||||||
{ "SAVE", CAP_SAVE },
|
{ "SAVE", CAP_SAVE },
|
||||||
{ "EUID", CAP_EUID },
|
{ "EUID", CAP_EUID },
|
||||||
{ "EOPMOD", CAP_EOPMOD },
|
{ "EOPMOD", CAP_EOPMOD },
|
||||||
|
{ "BAN", CAP_BAN },
|
||||||
{0, 0}
|
{0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -392,6 +393,67 @@ send_capabilities(struct Client *client_p, int cap_can_send)
|
||||||
sendto_one(client_p, "CAPAB :%s", msgbuf);
|
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()
|
/* burst_modes_TS6()
|
||||||
*
|
*
|
||||||
* input - client to burst to, channel name, list to burst, mode flag
|
* 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);
|
target_p->serv->fullcaps);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(IsCapable(client_p, CAP_BAN))
|
||||||
|
burst_ban(client_p);
|
||||||
|
|
||||||
burst_TS6(client_p);
|
burst_TS6(client_p);
|
||||||
|
|
||||||
/* Always send a PING after connect burst is done */
|
/* Always send a PING after connect burst is done */
|
||||||
|
|
Loading…
Reference in New Issue