This repository has been archived on 2025-02-12. You can view files and clone it, but cannot push or open issues or pull requests.
NeoStats-NeoIRCd/modules/m_kline.c
2002-10-23 03:53:22 +00:00

1176 lines
30 KiB
C

/*
* NeoIRCd: NeoStats Group. Based on Hybird7
* m_kline.c: Bans a user.
*
* Copyright (C) 2002 by the past and present ircd coders, and others.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*
* $Id: m_kline.c,v 1.12 2002/10/23 03:53:21 fishwaldo Exp $
*/
#include "stdinc.h"
#include "tools.h"
#include "m_kline.h"
#include "channel.h"
#include "class.h"
#include "client.h"
#include "common.h"
#include "irc_string.h"
#include "ircd.h"
#include "hostmask.h"
#include "numeric.h"
#include "fdlist.h"
#include "s_bsd.h"
#include "s_conf.h"
#include "s_log.h"
#include "s_misc.h"
#include "send.h"
#include "hash.h"
#include "handlers.h"
#include "s_serv.h"
#include "msg.h"
#include "parse.h"
#include "modules.h"
#include "list.h"
static void mo_unkline(struct Client*, struct Client*, int, char**);
static void mo_kline(struct Client *,struct Client *,int,char **);
static void ms_kline(struct Client *,struct Client *,int,char **);
static void mo_dline(struct Client *,struct Client *,int,char **);
static void mo_undline(struct Client*, struct Client*, int, char**);
struct Message kline_msgtab[] = {
{"KLINE", 0, 0, 2, 0, MFLG_SLOW, 0,
{m_unregistered, m_not_oper, ms_kline, mo_kline}},
{"UNKLINE", 0, 0, 2, 0, MFLG_SLOW, 0,
{m_unregistered, m_not_oper, m_error, mo_unkline}},
};
struct Message dline_msgtab[] = {
{"DLINE", 0, 0, 2, 0, MFLG_SLOW, 0,
{m_unregistered, m_not_oper, mo_dline, mo_dline}},
{"UNDLINE", 0, 0, 2, 0, MFLG_SLOW, 0,
{m_unregistered, m_not_oper, mo_undline, mo_undline}},
};
#ifndef STATIC_MODULES
void
_modinit(void)
{
mod_add_cmd(&kline_msgtab[0]);
mod_add_cmd(&kline_msgtab[1]);
mod_add_cmd(&dline_msgtab[0]);
mod_add_cmd(&dline_msgtab[1]);
}
void
_moddeinit(void)
{
mod_del_cmd(&kline_msgtab[0]);
mod_del_cmd(&kline_msgtab[1]);
mod_del_cmd(&dline_msgtab[0]);
mod_del_cmd(&dline_msgtab[1]);
}
const char *_version = "$Revision: 1.12 $";
#endif
/* Local function prototypes */
static time_t valid_tkline(struct Client *source_p, char *string);
static char *cluster(char *);
static int find_user_host(struct Client *source_p,
char *user_host_or_nick, char *user, char *host);
/* needed to remove unused definition warning */
static int valid_comment(struct Client *source_p, char *comment);
static int valid_user_host(struct Client *source_p, char *user, char *host);
static int valid_wild_card(char *user, char *host);
static int already_placed_kline(struct Client*, char*, char*);
static void apply_kline(struct Client *source_p, struct ConfItem *aconf,
const char *reason, const char *oper_reason,
const char *current_date, time_t cur_time);
static void apply_tkline(struct Client *source_p, struct ConfItem *aconf,
const char *current_date, int temporary_kline_time);
char buffer[IRCD_BUFSIZE];
char user[USERLEN+2];
char host[HOSTLEN+2];
#define MAX_EXT_REASON 100
/*
* mo_kline
*
* inputs - pointer to server
* - pointer to client
* - parameter count
* - parameter list
* output -
* side effects - k line is added
*
*/
static void
mo_kline(struct Client *client_p, struct Client *source_p,
int parc, char **parv)
{
char *reason = "No Reason";
char *oper_reason;
const char* current_date;
const char* target_server=NULL;
struct ConfItem *aconf;
time_t tkline_time=0;
time_t cur_time;
if (!IsOperK(source_p))
{
sendto_one(source_p,":%s NOTICE %s :You need kline = yes;",
me.name,source_p->name);
return;
}
parv++;
parc--;
tkline_time = valid_tkline(source_p,*parv);
if (tkline_time > 0)
{
parv++;
parc--;
}
if (parc == 0)
{
sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
me.name, source_p->name, "KLINE");
return;
}
if (find_user_host(source_p, *parv, user, host) == 0)
return;
parc--;
parv++;
if (parc != 0)
{
if (irccmp(*parv,"ON") == 0)
{
parc--;
parv++;
if(parc == 0)
{
sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
me.name, source_p->name, "KLINE");
return;
}
target_server = *parv;
parc--;
parv++;
}
}
if(parc != 0)
reason = *parv;
if (valid_user_host(source_p, user,host))
return;
if (valid_wild_card(user,host))
{
sendto_one(source_p,
":%s NOTICE %s :Please include at least %d non-wildcard characters with the user@host",
me.name,
source_p->name,
ConfigFileEntry.min_nonwildcard);
return;
}
if (!valid_comment(source_p, reason))
return;
set_time();
cur_time = CurrentTime;
current_date = smalldate(cur_time);
aconf = make_conf();
aconf->status = CONF_KILL;
DupString(aconf->host, host);
DupString(aconf->user, user);
aconf->port = 0;
if (target_server != NULL)
{
sendto_server(NULL, source_p, NULL, NOCAPS, NOCAPS, LL_ICLIENT,
":%s KLINE %s %lu %s %s :%s",
source_p->name,
target_server,
(unsigned long) tkline_time,
user, host, reason);
/* If we are sending it somewhere that doesnt include us, we stop
* else we apply it locally too
*/
if (!match(target_server, me.name))
return;
}
if (already_placed_kline(source_p, user, host))
return;
/* Look for an oper reason */
if ((oper_reason = strchr(reason, '|')) != NULL)
{
*oper_reason = '\0';
oper_reason++;
}
if (tkline_time)
{
ircsprintf(buffer,
"Temporary K-line %d min. - %s (%s)",
(int)(tkline_time/60),
reason,
current_date);
DupString(aconf->passwd, buffer);
apply_tkline(source_p, aconf, current_date, tkline_time);
}
else
{
ircsprintf(buffer, "%s (%s)",
reason,
current_date);
DupString(aconf->passwd, buffer);
apply_kline(source_p, aconf, reason, oper_reason,
current_date, cur_time);
}
} /* mo_kline() */
/*
* ms_kline()
*
*
*/
static void
ms_kline(struct Client *client_p, struct Client *source_p,
int parc, char *parv[])
{
const char *current_date;
struct ConfItem *aconf=NULL;
int tkline_time;
time_t cur_time;
char *kuser;
char *khost;
char *kreason;
if (parc != 6)
return;
/* parv[0] parv[1] parv[2] parv[3] parv[4] parv[5] */
/* oper target_server tkline_time user host reason */
sendto_server(client_p, source_p, NULL, NOCAPS, NOCAPS, LL_ICLIENT,
":%s KLINE %s %s %s %s :%s",
parv[0], parv[1], parv[2], parv[3], parv[4], parv[5]);
kuser = parv[3];
khost = parv[4];
kreason = parv[5];
if (!match(parv[1],me.name))
return;
if (!IsPerson(source_p))
return;
if (valid_user_host(source_p, kuser, khost))
{
sendto_realops_flags(FLAGS_ALL|FLAGS_REMOTE, L_ALL,
"*** %s!%s@%s on %s is requesting an Invalid K-Line for [%s@%s] [%s]",
source_p->name, source_p->username, source_p->host, source_p->user->server,
kuser, khost, kreason);
return;
}
if (valid_wild_card(kuser, khost))
{
sendto_realops_flags(FLAGS_ALL|FLAGS_REMOTE, L_ALL,
"*** %s!%s@%s on %s is requesting a K-Line without %d wildcard chars for [%s@%s] [%s]",
source_p->name, source_p->username, source_p->host, source_p->user->server,
ConfigFileEntry.min_nonwildcard, kuser, khost, kreason);
return;
}
if(!valid_comment(source_p, kreason))
return;
tkline_time = atoi(parv[2]);
if (IsUlined(source_p) || IsServices(source_p))
{
sendto_realops_flags(FLAGS_ALL, L_ALL,
"*** Received K-Line for [%s@%s] [%s], from %s!%s@%s on %s",
kuser, khost, kreason,
source_p->name, source_p->username,
source_p->host, source_p->user->server);
/* We check if the kline already exists after we've announced its
* arrived, to avoid confusing opers - fl
*/
if (already_placed_kline(source_p, kuser, khost))
return;
aconf = make_conf();
aconf->status = CONF_KILL;
DupString(aconf->user, kuser);
DupString(aconf->host, khost);
DupString(aconf->passwd, kreason);
current_date = smalldate((time_t) 0);
set_time();
cur_time = CurrentTime;
if (tkline_time)
apply_tkline(source_p, aconf, current_date, tkline_time);
else
apply_kline(source_p, aconf, aconf->passwd, NULL,
current_date, cur_time);
}
} /* ms_kline() */
/*
* apply_kline
*
* inputs -
* output - NONE
* side effects - kline as given, is added to the hashtable
* and conf file
*/
static void
apply_kline(struct Client *source_p, struct ConfItem *aconf,
const char *reason, const char *oper_reason,
const char *current_date, time_t cur_time)
{
add_conf_by_address(aconf->host, CONF_KILL, aconf->user, aconf);
/* Now, activate kline against current online clients */
check_klines();
}
/*
* apply_tkline
*
* inputs -
* output - NONE
* side effects - tkline as given is placed
*/
static void
apply_tkline(struct Client *source_p, struct ConfItem *aconf,
const char *current_date, int tkline_time)
{
aconf->hold = CurrentTime + tkline_time;
add_temp_kline(aconf);
sendto_realops_flags(FLAGS_ALL, L_ALL,
"%s added temporary %d min. K-Line for [%s@%s] [%s]",
get_oper_name(source_p), tkline_time/60,
aconf->user, aconf->host,
aconf->passwd);
sendto_one(source_p, ":%s NOTICE %s :Added temporary %d min. K-Line [%s@%s]",
me.name, source_p->name, tkline_time/60,
aconf->user, aconf->host);
ilog(L_TRACE, "%s added temporary %d min. K-Line for [%s@%s] [%s]",
source_p->name, tkline_time/60,
aconf->user, aconf->host, aconf->passwd);
check_klines();
}
/*
* valid_tkline()
*
* inputs - pointer to client requesting kline
* - argument count
* - pointer to ascii string in
* output - -1 not enough parameters
* - 0 if not an integer number, else the number
* side effects - none
*/
static time_t
valid_tkline(struct Client *source_p, char *p)
{
time_t result = 0;
while(*p)
{
if(IsDigit(*p))
{
result *= 10;
result += ((*p) & 0xF);
p++;
}
else
return(0);
}
/* in the degenerate case where oper does a /quote kline 0 user@host :reason
* i.e. they specifically use 0, I am going to return 1 instead
* as a return value of non-zero is used to flag it as a temporary kline
*/
if(result == 0)
result = 1;
if(result > (24*60))
result = (24*60); /* Max it at 24 hours */
result = (time_t)result * (time_t)60; /* turn it into seconds */
return(result);
}
/*
* cluster()
*
* inputs - pointer to a hostname
* output - pointer to a static of the hostname masked
* for use in a kline.
* side effects - NONE
*
*/
static char *
cluster(char *hostname)
{
static char result[HOSTLEN + 1]; /* result to return */
char temphost[HOSTLEN + 1]; /* work place */
char *ipp; /* used to find if host is ip # only */
char *host_mask; /* used to find host mask portion to '*' */
char *zap_point = NULL; /* used to zap last nnn portion of an ip # */
char *tld; /* Top Level Domain */
int is_ip_number; /* flag if its an ip # */
int number_of_dots; /* count number of dots for both ip# and
domain klines */
if (!hostname)
return (char *) NULL; /* EEK! */
/* If a '@' is found in the hostname, this is bogus
* and must have been introduced by server that doesn't
* check for bogus domains (dns spoof) very well. *sigh* just return it...
* I could also legitimately return (char *)NULL as above.
*/
if(strchr(hostname,'@'))
{
strlcpy(result, hostname, HOSTLEN + 1);
return(result);
}
strlcpy(temphost, hostname, HOSTLEN + 1);
is_ip_number = YES; /* assume its an IP# */
ipp = temphost;
number_of_dots = 0;
while (*ipp)
{
if(*ipp == '.')
{
number_of_dots++;
if(number_of_dots == 3)
zap_point = ipp;
ipp++;
}
else if(!IsDigit(*ipp))
{
is_ip_number = NO;
break;
}
ipp++;
}
if (is_ip_number && (number_of_dots == 3))
{
zap_point++;
*zap_point++ = '*'; /* turn 111.222.333.444 into */
*zap_point = '\0'; /* 111.222.333.* */
strlcpy(result, temphost, HOSTLEN + 1);
return(result);
}
else
{
tld = strrchr(temphost, '.');
if(tld)
{
number_of_dots = 2;
if(tld[3]) /* its at least a 3 letter tld
i.e. ".com" tld[3] = 'm' not
'\0' */
/* 4 letter tld's are coming */
number_of_dots = 1;
if(tld != temphost) /* in these days of dns spoofers ...*/
host_mask = tld - 1; /* Look for host portion to '*' */
else
host_mask = tld; /* degenerate case hostname is
'.com' etc. */
while (host_mask != temphost)
{
if(*host_mask == '.')
number_of_dots--;
if(number_of_dots == 0)
{
result[0] = '*';
strlcpy(result + 1, host_mask, HOSTLEN + 1);
return(result);
}
host_mask--;
}
result[0] = '*'; /* foo.com => *foo.com */
strlcpy(result + 1, temphost, HOSTLEN + 1);
}
else /* no tld found oops. just return it as is */
{
strlcpy(result, temphost, HOSTLEN + 1);
return(result);
}
}
return (result);
}
/*
* mo_dline
*
* inputs - pointer to server
* - pointer to client
* - parameter count
* - parameter list
* output -
* side effects - D line is added
*
*/
static void
mo_dline(struct Client *client_p, struct Client *source_p,
int parc, char *parv[])
{
char *dlhost, *reason, *oper_reason;
#ifndef IPV6
char *p;
struct Client *target_p;
#endif
struct irc_inaddr daddr;
char cidr_form_host[HOSTLEN + 1];
struct ConfItem *aconf;
int bits, t;
char dlbuffer[1024];
const char* current_date;
time_t cur_time;
dlhost = parv[1];
strlcpy(cidr_form_host, dlhost, HOSTLEN + 1);
cidr_form_host[HOSTLEN] = '\0';
if ((t=parse_netmask(dlhost, NULL, &bits)) == HM_HOST)
{
#ifdef IPV6
if (!IsServices(source_p)) {
sendto_one(source_p, ":%s NOTICE %s :Sorry, please supply an address.", me.name, parv[0]);
return;
}
#else
if (!(target_p = find_chasing(source_p, parv[1], NULL)))
return;
if(!target_p->user)
return;
t = HM_IPV4;
if (IsServer(target_p))
{
if (!IsServices(source_p)) sendto_one(source_p,
":%s NOTICE %s :Can't DLINE a server silly",
me.name, parv[0]);
return;
}
if (!MyConnect(target_p))
{
if (!IsServices(source_p)) sendto_one(source_p,
":%s NOTICE :%s :Can't DLINE nick on another server",
me.name, parv[0]);
return;
}
if (IsExemptKline(target_p))
{
if (!IsServices(source_p)) sendto_one(source_p,
":%s NOTICE %s :%s is E-lined",me.name,parv[0],
target_p->name);
return;
}
/*
* XXX - this is always a fixed length output, we can get away
* with strcpy here
*
* strncpy_irc(cidr_form_host, inetntoa((char *)&target_p->ip), 32);
* cidr_form_host[32] = '\0';
*/
strcpy(cidr_form_host, inetntoa((char*) &target_p->localClient->ip));
if ((p = strchr(cidr_form_host,'.')) == NULL)
return;
/* 192. <- p */
p++;
if ((p = strchr(p,'.')) == NULL)
return;
/* 192.168. <- p */
p++;
if ((p = strchr(p,'.')) == NULL)
return;
/* 192.168.0. <- p */
p++;
*p++ = '0';
*p++ = '/';
*p++ = '2';
*p++ = '4';
*p++ = '\0';
dlhost = cidr_form_host;
bits = 0xFFFFFF00UL;
/* XXX: Fix me for IPV6 */
#endif
}
if (parc > 2) /* host :reason */
{
if (valid_comment(source_p,parv[2]) == 0)
return;
if(*parv[2])
reason = parv[2];
else
reason = "No reason";
}
else
reason = "No reason";
if (IsOperAdmin(source_p))
{
if (bits < 8)
{
if (!IsServices(source_p)) sendto_one(source_p,
":%s NOTICE %s :For safety, bitmasks less than 8 require conf access.",
me.name, parv[0]);
return;
}
}
else
{
if ((bits < 24) && !IsServices(source_p))
{
sendto_one(source_p,
":%s NOTICE %s :Dline bitmasks less than 24 are for admins only.",
me.name, parv[0]);
return;
}
}
#ifdef IPV6
if (t == HM_IPV6)
t = AF_INET6;
else
#endif
t = AF_INET;
if (ConfigFileEntry.non_redundant_klines)
{
char *creason;
(void)parse_netmask(dlhost, &daddr, NULL);
if((aconf = find_dline_conf(&daddr, t)) != NULL)
{
creason = aconf->passwd ? aconf->passwd : "<No Reason>";
if (IsConfExemptKline(aconf)) {
if (!IsServices(source_p)) sendto_one(source_p,
":%s NOTICE %s :[%s] is (E)d-lined by [%s] - %s",
me.name, parv[0], dlhost, aconf->host, creason);
} else {
if (!IsServices(source_p)) sendto_one(source_p,
":%s NOTICE %s :[%s] already D-lined by [%s] - %s",
me.name, parv[0], dlhost, aconf->host, creason);
}
return;
}
}
set_time();
cur_time = CurrentTime;
current_date = smalldate(cur_time);
aconf = make_conf();
/* Look for an oper reason */
if ((oper_reason = strchr(reason, '|')) != NULL)
{
*oper_reason = '\0';
oper_reason++;
}
ircsprintf(dlbuffer, "%s (%s)",reason, current_date);
aconf->status = CONF_DLINE;
DupString(aconf->host, dlhost);
DupString(aconf->passwd, dlbuffer);
add_conf_by_address(aconf->host, CONF_DLINE, NULL, aconf);
check_klines();
if (!IsServices(source_p)) sendto_one(source_p, ":%s NOTICE %s :[%s] has been dlined", me.name, source_p->name, parv[1]);
sendto_realops_flags(FLAGS_ALL, L_ALL, "*** %s has Dlined %s for %s", source_p->name, parv[1], reason);
sendto_server(client_p, NULL, NULL, NOCAPS, NOCAPS, NOFLAGS, ":%s DLINE %s :%s", source_p->name, parv[1], parv[2] ? parv[2] : "");
} /* m_dline() */
/*
* find_user_host
* inputs - pointer to client placing kline
* - pointer to user_host_or_nick
* - pointer to user buffer
* - pointer to host buffer
* output - 0 if not ok to kline, 1 to kline i.e. if valid user host
* side effects -
*/
static int
find_user_host(struct Client *source_p,
char *user_host_or_nick, char *luser, char *lhost)
{
struct Client *target_p;
char *hostp;
if ((hostp = strchr(user_host_or_nick, '@')) || *user_host_or_nick == '*')
{
/* Explicit user@host mask given */
if(hostp != NULL) /* I'm a little user@host */
{
*(hostp++) = '\0'; /* short and squat */
if (*user_host_or_nick)
strlcpy(luser,user_host_or_nick,USERLEN + 1); /* here is my user */
else
strcpy(luser,"*");
if (*hostp)
strlcpy(lhost, hostp, HOSTLEN + 1); /* here is my host */
else
strcpy(lhost,"*");
}
else
{
luser[0] = '*'; /* no @ found, assume its *@somehost */
luser[1] = '\0';
strlcpy(lhost, user_host_or_nick, HOSTLEN + 1);
}
return 1;
}
else
{
/* Try to find user@host mask from nick */
if (!(target_p = find_chasing(source_p, user_host_or_nick, NULL)))
return 0;
if(!target_p->user)
return 0;
if (IsServer(target_p))
{
sendto_one(source_p,
":%s NOTICE %s :Can't KLINE a server, use @'s where appropriate",
me.name, source_p->name);
return 0;
}
if(IsExemptKline(target_p))
{
if(!IsServer(source_p))
sendto_one(source_p,
":%s NOTICE %s :%s is E-lined",me.name,source_p->name,
target_p->name);
return 0;
}
/* turn the "user" bit into "*user", blow away '~'
* if found in original user name (non-idented)
*/
strlcpy(luser, target_p->username, USERLEN + 1);
if (*target_p->username == '~')
luser[0] = '*';
strlcpy(lhost,cluster(target_p->host), HOSTLEN + 1);
}
return 1;
}
/*
* valid_user_host
* inputs - pointer to source
* - pointer to user buffer
* - pointer to host buffer
* output - 1 if not valid user or host, 0 if valid
* side effects -
*/
static int
valid_user_host(struct Client *source_p, char *luser, char *lhost)
{
/*
* Check for # in user@host
*/
if(strchr(lhost, '#') || strchr(luser, '#'))
{
sendto_one(source_p, ":%s NOTICE %s :Invalid character '#' in kline",
me.name, source_p->name);
return 1;
}
/* Dont let people kline *!ident@host, as the ! is invalid.. */
if(strchr(luser, '!'))
{
sendto_one(source_p, ":%s NOTICE %s :Invalid character '!' in kline",
me.name, source_p->name);
return 1;
}
return 0;
}
/*
* valid_wild_card
* input - pointer to client
* - pointer to user to check
* - pointer to host to check
* output - 0 if not valid, 1 if valid
* side effects -
*/
static int
valid_wild_card(char *luser, char *lhost)
{
char *p;
char tmpch;
int nonwild;
/*
* Now we must check the user and host to make sure there
* are at least NONWILDCHARS non-wildcard characters in
* them, otherwise assume they are attempting to kline
* *@* or some variant of that. This code will also catch
* people attempting to kline *@*.tld, as long as NONWILDCHARS
* is greater than 3. In that case, there are only 3 non-wild
* characters (tld), so if NONWILDCHARS is 4, the kline will
* be disallowed.
* -wnder
*/
nonwild = 0;
p = luser;
while ((tmpch = *p++))
{
if (!IsKWildChar(tmpch))
{
/*
* If we find enough non-wild characters, we can
* break - no point in searching further.
*/
if (++nonwild >= ConfigFileEntry.min_nonwildcard)
break;
}
}
if (nonwild < ConfigFileEntry.min_nonwildcard)
{
/*
* The user portion did not contain enough non-wild
* characters, try the host.
*/
p = lhost;
while ((tmpch = *p++))
{
if (!IsKWildChar(tmpch))
if (++nonwild >= ConfigFileEntry.min_nonwildcard)
break;
}
}
if (nonwild < ConfigFileEntry.min_nonwildcard)
return 1;
else
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(source_p,
":%s NOTICE %s :Invalid character '\"' in comment",
me.name, source_p->name);
return 0;
}
return 1;
}
/* static int already_placed_kline(source_p, luser, lhost)
* Input: user to complain to, username & host to check for.
* Output: returns 1 on existing K-line, 0 if doesn't exist.
* Side-effects: Notifies source_p if the K-line already exists.
* Note: This currently works if the new K-line is a special case of an
* existing K-line, but not the other way round. To do that we would
* have to walk the hash and check every existing K-line. -A1kmm.
*/
static int
already_placed_kline(struct Client *source_p, char *luser, char *lhost)
{
char *reason;
struct irc_inaddr iphost, *piphost;
struct ConfItem *aconf;
int t;
if (ConfigFileEntry.non_redundant_klines)
{
if ((t=parse_netmask(lhost, &iphost, &t)) != HM_HOST)
{
#ifdef IPV6
if (t == HM_IPV6)
t = AF_INET6;
else
#endif
t = AF_INET;
piphost = &iphost;
}
else
{
t = 0;
piphost = NULL;
}
if ((aconf = find_conf_by_address(lhost, piphost, CONF_KILL, t, luser)))
{
reason = aconf->passwd ? aconf->passwd : "<No Reason>";
/* Remote servers can set klines, so if its a dupe we warn all
* local opers and leave it at that
*/
/* they can? here was me thinking it was only remote clients :P */
if(!MyClient(source_p))
sendto_realops_flags(FLAGS_ALL|FLAGS_REMOTE, L_ALL,
"*** Remote K-Line [%s@%s] already K-Lined by [%s@%s] - %s",
luser, lhost, aconf->user, aconf->host, reason);
else
sendto_one(source_p,
":%s NOTICE %s :[%s@%s] already K-Lined by [%s@%s] - %s",
me.name, source_p->name, luser, lhost, aconf->user,
aconf->host, reason);
return 1;
}
}
return 0;
}
static int remove_tkline_match(char *,char *);
/*
** mo_unkline
** Added Aug 31, 1997
** common (Keith Fralick) fralick@gate.net
**
** parv[0] = sender
** parv[1] = address to remove
*
*
*/
static void mo_unkline (struct Client *client_p,struct Client *source_p,
int parc,char *parv[])
{
char *kuser, *khost;
if (!IsOperUnkline(source_p))
{
sendto_one(source_p,":%s NOTICE %s :You need unkline = yes;",me.name,parv[0]);
return;
}
if (parc < 2)
{
sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
me.name, source_p->name, "UNKLINE");
return;
}
if ((khost = strchr(parv[1], '@')) || *parv[1] == '*')
{
/* Explicit user@host mask given */
if(khost) /* Found user@host */
{
kuser = parv[1]; /* here is user part */
*(khost++) = '\0'; /* and now here is host */
}
else
{
kuser = "*"; /* no @ found, assume its *@somehost */
khost = parv[1];
}
}
else
{
sendto_one(source_p, ":%s NOTICE %s :Invalid parameters",
me.name, source_p->name);
return;
}
if (remove_tkline_match(khost, kuser))
{
sendto_one(source_p,
":%s NOTICE %s :Un-klined [%s@%s] from temporary k-lines",
me.name, parv[0],kuser, khost);
sendto_realops_flags(FLAGS_ALL, L_ALL,
"%s has removed the temporary K-Line for: [%s@%s]",
get_oper_name(source_p), kuser, khost);
ilog(L_NOTICE, "%s removed temporary K-Line for [%s@%s]", parv[0], kuser,
khost);
return;
}
else
{
sendto_one(source_p, ":%s NOTICE %s :No K-Line for %s@%s",
me.name, source_p->name,kuser,khost);
return;
}
return;
}
/* static int remove_tkline_match(char *host, char *user)
* Input: A hostname, a username to unkline.
* Output: returns YES on success, NO if no tkline removed.
* Side effects: Any matching tklines are removed.
*/
static int
remove_tkline_match(char *khost, char *kuser)
{
struct ConfItem *tk_c;
dlink_node *tk_n;
struct irc_inaddr addr, caddr;
int nm_t, cnm_t, bits, cbits;
nm_t = parse_netmask(khost, &addr, &bits);
for (tk_n=temporary_klines.head; tk_n; tk_n=tk_n->next)
{
tk_c = (struct ConfItem*)tk_n->data;
cnm_t = parse_netmask(tk_c->host, &caddr, &cbits);
if (cnm_t != nm_t || irccmp(kuser, tk_c->user))
continue;
if ((nm_t==HM_HOST && !irccmp(tk_c->host, khost)) ||
(nm_t==HM_IPV4 && bits==cbits && match_ipv4(&addr, &caddr, bits))
#ifdef IPV6
|| (nm_t==HM_IPV6 && bits==cbits && match_ipv6(&addr, &caddr, bits))
#endif
)
{
dlinkDelete(tk_n, &temporary_klines);
free_dlink_node(tk_n);
delete_one_address_conf(tk_c->host, tk_c);
return YES;
}
}
return NO;
}
/*
** m_undline
** added May 28th 2000 by Toby Verrall <toot@melnet.co.uk>
** based totally on m_unkline
** added to hybrid-7 7/11/2000 --is
**
** parv[0] = sender nick
** parv[1] = dline to remove
*/
static void
mo_undline (struct Client *client_p, struct Client *source_p,
int parc,char *parv[])
{
struct ConfItem *aconf;
char *cidr;
int t;
struct irc_inaddr daddr;
cidr = parv[1];
t = 0;
#if 0
if ((type=parse_netmask(cidr,&ip_host,&ip_mask)) == HM_HOST)
{
sendto_one(source_p, ":%s NOTICE %s :Invalid parameters",
me.name, parv[0]);
return;
}
#endif
sendto_server(client_p, NULL, NULL, NOCAPS, NOCAPS, NOFLAGS, ":%s UNDLINE %s", source_p->name, cidr);
/* TODO : remove dline */
sendto_one(source_p, ":%s NOTICE %s :%d %s", me.name, source_p->name, t, cidr);
t = parse_netmask(cidr, &daddr, NULL);
#ifdef IPV6
if (t == HM_IPV6)
t = AF_INET6;
else
#endif
t = AF_INET;
if((aconf = find_dline_conf(&daddr, t)) != NULL) {
delete_one_address_conf(aconf->host, aconf);
sendto_one(source_p, ":%s NOTICE %s :D-Line for [%s] is removed",
me.name, parv[0], cidr);
sendto_realops_flags(FLAGS_ALL, L_ALL, "%s has removed the D-Line for: [%s]",
get_oper_name(source_p), cidr);
ilog(L_NOTICE, "%s removed D-Line for [%s]", get_oper_name(source_p),
cidr);
} else {
sendto_one(source_p, ":%s NOTICE %s :D-Line %s can not be found", me.name, source_p->name, cidr);
}
}