/* Local function prototypes */
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);
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()
*
struct ConfItem *aconf;
int tkline_time = 0;
int loc = 1;
+ int propagated = ConfigFileEntry.use_propagated_bans;
if(!IsOperK(source_p))
{
/* 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);
- if(!valid_user_host(source_p, user, host) ||
- !valid_wild_card(source_p, user, host) || !valid_comment(source_p, reason))
+ if(!valid_user_host(source_p, user, host))
+ 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");
+ return 0;
+ }
if(already_placed_kline(source_p, user, host, tkline_time))
return 0;
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));
+ if(strlen(reason) > BANREASONLEN)
+ reason[BANREASONLEN] = '\0';
+
/* Look for an oper reason */
if((oper_reason = strchr(reason, '|')) != NULL)
{
if(!EmptyString(oper_reason))
aconf->spasswd = rb_strdup(oper_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);
else
apply_kline(source_p, aconf, reason, oper_reason);
(tkline_time > 0) ? SHARED_TKLINE : SHARED_PKLINE))
return;
- if(!valid_user_host(source_p, user, host) ||
- !valid_wild_card(source_p, user, host) || !valid_comment(source_p, reason))
+ if(!valid_user_host(source_p, user, host))
+ 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;
+ }
if(already_placed_kline(source_p, user, host, tkline_time))
return;
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));
+ if(strlen(reason) > BANREASONLEN)
+ reason[BANREASONLEN] = '\0';
+
/* Look for an oper reason */
if((oper_reason = strchr(reason, '|')) != NULL)
{
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);
char splat[] = "*";
char *h = LOCAL_COPY(parv[1]);
struct ConfItem *aconf;
+ int propagated = 1;
if(!IsOperUnkline(source_p))
{
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;
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;
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)
+{
+ aconf->flags |= CONF_FLAGS_MYOPER | CONF_FLAGS_TEMPORARY;
+ aconf->hold = rb_current_time() + tkline_time;
+ aconf->lifetime = aconf->hold;
+
+ replace_old_ban(aconf);
+
+ 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
rb_strlcpy(lhost, userhost, HOSTLEN + 1);
}
+ /* would break the protocol */
+ if (*luser == ':' || *lhost == ':')
+ {
+ sendto_one_notice(source_p, ":Invalid K-Line");
+ return 0;
+ }
+
return 1;
}
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
- * - pointer to comment
- * output - 0 if no valid comment, 1 if valid
- * side effects - NONE
- */
-static int
-valid_comment(struct Client *source_p, char *comment)
-{
- if(strchr(comment, '"'))
- {
- sendto_one_notice(source_p, ":Invalid character '\"' in comment");
- return 0;
- }
-
- if(strlen(comment) > BANREASONLEN)
- comment[BANREASONLEN] = '\0';
-
- return 1;
-}
-
/* already_placed_kline()
*
* inputs - source to notify, user@host to check, tkline time
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++;
+ 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 * :*",
+ 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);
+}