1176 lines
30 KiB
C
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);
|
|
}
|
|
}
|
|
|
|
|