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_gline.c

655 lines
18 KiB
C
Raw Permalink Normal View History

2002-08-13 14:34:25 +00:00
/*
* NeoIRCd: NeoStats Group. Based on Hybird7
2002-08-13 14:34:25 +00:00
* m_gline.c: Votes towards globally banning a mask.
*
* 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
*
2002-09-23 03:30:25 +00:00
* $Id: m_gline.c,v 1.9 2002/09/23 03:30:25 fishwaldo Exp $
2002-08-13 14:34:25 +00:00
*/
#include "stdinc.h"
#include "tools.h"
#include "handlers.h"
#include "s_gline.h"
#include "channel.h"
#include "client.h"
#include "common.h"
#include "config.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_misc.h"
#include "scache.h"
#include "send.h"
#include "msg.h"
#include "fileio.h"
#include "s_serv.h"
#include "hash.h"
#include "parse.h"
#include "modules.h"
#include "list.h"
#include "s_log.h"
2002-08-13 14:34:25 +00:00
/* internal functions */
static void set_local_gline(
const char *oper_nick,
const char *oper_user,
const char *oper_host,
const char *oper_server,
const char *user,
const char *host,
2002-09-22 03:36:42 +00:00
unsigned long bantime,
2002-08-13 14:34:25 +00:00
const char *reason);
static void log_gline(const char *, const char *,const char *,
2002-08-13 14:34:25 +00:00
const char* oper_server,
2002-09-22 03:36:42 +00:00
const char *,const char *,unsigned long bantime, const char *);
2002-08-13 14:34:25 +00:00
static int check_wild_gline(char *, char *);
static int invalid_gline(struct Client *, char *, char *, char *);
static void ms_gline(struct Client*, struct Client*, int, char**);
static void mo_gline(struct Client*, struct Client*, int, char**);
static void mo_ungline(struct Client*, struct Client*, int, char**);
2002-09-13 16:30:05 +00:00
static void ms_ungline(struct Client *, struct Client *,int ,char **);
2002-08-13 14:34:25 +00:00
struct Message gline_msgtab[] = {
2002-09-22 03:36:42 +00:00
{"GLINE", 0, 0, 4, 0, MFLG_SLOW, 0,
{m_unregistered, m_not_oper, ms_gline, mo_gline}},
{"UNGLINE", 0, 0, 2, 0, MFLG_SLOW, 0,
2002-09-13 16:30:05 +00:00
{m_unregistered, m_not_oper, ms_ungline, mo_ungline}}
2002-08-13 14:34:25 +00:00
};
#ifndef STATIC_MODULES
void
_modinit(void)
{
mod_add_cmd(&gline_msgtab[0]);
mod_add_cmd(&gline_msgtab[1]);
2002-08-13 14:34:25 +00:00
}
void
_moddeinit(void)
{
mod_del_cmd(&gline_msgtab[0]);
mod_del_cmd(&gline_msgtab[1]);
2002-08-13 14:34:25 +00:00
}
2002-09-23 03:30:25 +00:00
const char *_version = "$Revision: 1.9 $";
2002-08-13 14:34:25 +00:00
#endif
/*
* mo_gline()
*
* inputs - The usual for a m_ function
* output -
* side effects -
*
* Place a G line if 3 opers agree on the identical user@host
*
*/
/* Allow this server to pass along GLINE if received and
* GLINES is not defined.
*
*/
static void
mo_gline(struct Client *client_p, struct Client *source_p,
int parc, char *parv[])
2002-08-13 14:34:25 +00:00
{
char *user = NULL;
char *host = NULL; /* user and host of GLINE "victim" */
const char *reason = NULL; /* reason for "victims" demise */
char tempuser[USERLEN + 2];
char temphost[HOSTLEN + 1];
2002-09-22 03:36:42 +00:00
unsigned long bantime;
2002-08-13 14:34:25 +00:00
if (ConfigFileEntry.glines)
{
if (!IsOperGline(source_p))
{
sendto_one(source_p,
":%s NOTICE %s :You need gline = yes;",me.name,parv[0]);
2002-08-13 14:34:25 +00:00
return;
}
if ( (host = strchr(parv[1], '@')) || *parv[1] == '*' )
{
/* Explicit user@host mask given */
if(host != NULL) /* Found user@host */
2002-08-13 14:34:25 +00:00
{
user = parv[1]; /* here is user part */
*(host++) = '\0'; /* and now here is host */
/* gline for "@host", use *@host */
if(*user == '\0')
user = "*";
2002-08-13 14:34:25 +00:00
}
else
{
user = "*"; /* no @ found, assume its *@somehost */
host = parv[1];
}
if (!*host) /* duh. no host found, assume its '*' host */
host = "*";
strlcpy(tempuser, user, USERLEN + 1); /* allow for '*' */
strlcpy(temphost, host, HOSTLEN + 1);
2002-08-13 14:34:25 +00:00
user = tempuser;
host = temphost;
}
else
{
sendto_one(source_p,
":%s NOTICE %s :Can't G-Line a nick use user@host",
me.name, parv[0]);
2002-08-13 14:34:25 +00:00
return;
}
if(invalid_gline(source_p, user, host, parv[2]))
return;
/* Not enough non-wild characters were found,
* assume they are trying to gline *@*.
*/
2002-08-13 14:34:25 +00:00
if (check_wild_gline(user, host))
{
if (MyClient(source_p))
sendto_one(source_p,
":%s NOTICE %s :Please include at least %d non-wildcard characters with the user@host",
me.name, parv[0], ConfigFileEntry.min_nonwildcard);
return;
}
2002-09-22 03:36:42 +00:00
reason = parv[3];
bantime = strtoul(parv[2], NULL, 10);
bantime = bantime * 60;
if (bantime == 0)
bantime = ConfigFileEntry.gline_time;
2002-08-13 14:34:25 +00:00
/* inform users about the gline before we call check_majority_gline()
* so already voted comes below gline request --fl
*/
sendto_realops_flags(FLAGS_ALL, L_ALL,
2002-09-22 03:36:42 +00:00
"%s!%s@%s on %s is requesting gline for [%s@%s] [%s] to last for %lu",
source_p->name, source_p->username, source_p->host,
2002-09-22 03:36:42 +00:00
me.name, user, host, reason, bantime);
2002-08-13 14:34:25 +00:00
2002-09-22 03:36:42 +00:00
set_local_gline(source_p->name, source_p->username, source_p->host, me.name, user, host, bantime + CurrentTime, reason);
log_gline(source_p->name, source_p->username, source_p->host, me.name, user, host, bantime + CurrentTime, reason);
2002-08-13 14:34:25 +00:00
/* 4 param version for hyb-7 servers */
sendto_server(NULL, source_p, NULL, CAP_UID, NOCAPS,
2002-08-13 14:34:25 +00:00
LL_ICLIENT,
2002-09-22 03:36:42 +00:00
":%s GLINE %s %s %lu :%s",
ID(source_p), user, host, bantime + CurrentTime, reason);
sendto_server(NULL, source_p, NULL, NOCAPS, CAP_UID,
2002-08-13 14:34:25 +00:00
LL_ICLIENT,
2002-09-22 03:36:42 +00:00
":%s GLINE %s %s %lu :%s",
source_p->name, user, host, bantime + CurrentTime, reason);
2002-08-13 14:34:25 +00:00
}
else
{
sendto_one(source_p,":%s NOTICE %s :GLINE disabled",me.name,parv[0]);
}
}
/*
* ms_gline()
*
* inputs - The usual for a m_ function
* output -
* side effects -
*
* Place a G line if 3 opers agree on the identical user@host
*
*/
/* Allow this server to pass along GLINE if received and
* GLINES is not defined.
*/
static void ms_gline(struct Client *client_p,
struct Client *source_p,
int parc,
char *parv[])
{
/* These are needed for hyb6 compatibility.. if its ever removed we can
* just use source_p->username etc..
*/
const char *oper_nick = NULL; /* nick of oper requesting GLINE */
const char *oper_user = NULL; /* username of oper requesting GLINE */
const char *oper_host = NULL; /* hostname of oper requesting GLINE */
const char *oper_server = NULL; /* server of oper requesting GLINE */
char *user = NULL;
char *host = NULL; /* user and host of GLINE "victim" */
const char *reason = NULL; /* reason for "victims" demise */
struct Client *acptr;
2002-09-22 03:36:42 +00:00
unsigned long bantime;
2002-09-13 16:30:05 +00:00
/* Gline has just been set by a user */
2002-08-13 14:34:25 +00:00
if(parc == 4 && IsPerson(source_p))
{
oper_nick = parv[0];
oper_user = source_p->username;
oper_host = source_p->host;
oper_server = source_p->user->server;
user = parv[1];
host = parv[2];
2002-09-22 03:36:42 +00:00
bantime = strtoul(parv[3], NULL, 10);
reason = parv[4];
2002-08-13 14:34:25 +00:00
}
2002-09-13 16:30:05 +00:00
/* gline coming in from a recently connected server */
else if (IsServer(source_p)) {
oper_server = parv[0];
user = parv[1];
host = parv[2];
2002-09-22 03:36:42 +00:00
bantime = strtoul(parv[3], NULL, 10);
reason = parv[4];
2002-09-13 16:30:05 +00:00
}
else
2002-08-13 14:34:25 +00:00
return;
2002-09-22 03:36:42 +00:00
if (bantime == 0)
bantime = ConfigFileEntry.gline_time;
2002-08-13 14:34:25 +00:00
/* Its plausible that the server and/or client dont actually exist,
* and its faked, as the oper isnt sending the gline..
* check they're real --fl_ */
/* we need acptr for LL introduction anyway -davidt */
2002-09-13 16:30:05 +00:00
if (IsServer(source_p))
acptr = find_server(source_p->name);
else {
if((acptr = find_server(oper_server)))
{
if((acptr = find_client(oper_nick)) == NULL)
return;
}
else
2002-08-13 14:34:25 +00:00
return;
}
2002-09-13 16:30:05 +00:00
if(invalid_gline(acptr, user, host, (char *)reason))
2002-08-13 14:34:25 +00:00
return;
/* send in hyb-7 to compatable servers */
sendto_server(client_p, acptr, NULL, NOCAPS, NOCAPS, LL_ICLIENT,
2002-09-22 03:36:42 +00:00
":%s GLINE %s %s %lu :%s",
parv[0], user, host, bantime, reason);
2002-08-13 14:34:25 +00:00
if (ConfigFileEntry.glines)
{
/* I dont like the idea of checking for x non-wildcard chars in a
* gline.. it could lead to a desync... but we have to stop people
* glining *@*.. -- fl
*/
2002-08-13 14:34:25 +00:00
if (check_wild_gline(user, host))
{
2002-09-13 16:30:05 +00:00
if (!IsServer(source_p))
sendto_realops_flags(FLAGS_ALL|FLAGS_REMOTE, L_ALL,
2002-08-13 14:34:25 +00:00
"%s!%s@%s on %s is requesting a gline without %d non-wildcard characters for [%s@%s] [%s]",
oper_nick, oper_user, oper_host, oper_server, ConfigFileEntry.min_nonwildcard,
user, host, reason);
return;
}
2002-09-13 16:30:05 +00:00
if(!IsServer(source_p))
sendto_realops_flags(FLAGS_ALL, L_ALL,
2002-09-22 03:36:42 +00:00
"%s!%s@%s on %s is requesting gline for [%s@%s] [%s] To expire at %lu",
2002-09-13 16:30:05 +00:00
oper_nick, oper_user, oper_host, oper_server,
2002-09-22 03:36:42 +00:00
user, host, reason, bantime);
2002-08-13 14:34:25 +00:00
2002-09-22 03:36:42 +00:00
set_local_gline(oper_nick, oper_user, oper_host, oper_server, user, host, bantime, reason);
if (!IsServer(source_p)) log_gline(oper_nick, oper_user, oper_host, oper_server, user, host, bantime, reason);
2002-08-13 14:34:25 +00:00
}
}
/*
* check_wild_gline
*
* inputs - user, host of gline
* output - 1 if not enough non-wildchar char's, 0 if ok
* side effects - NONE
*/
static int
check_wild_gline(char *user, char *host)
{
char *p;
char tmpch;
int nonwild;
nonwild = 0;
p = user;
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 = host;
while ((tmpch = *p++))
{
if (!IsKWildChar(tmpch))
if (++nonwild >= ConfigFileEntry.min_nonwildcard)
break;
}
}
if (nonwild < ConfigFileEntry.min_nonwildcard)
return 1;
else
return 0;
}
/* invalid_gline
*
* inputs - pointer to source client
* - pointer to ident
* - pointer to host
* - pointer to reason
* outputs - 1 if invalid, 0 if valid
*/
static int
invalid_gline(struct Client *source_p, char *luser, char *lhost,
2002-08-13 14:34:25 +00:00
char *lreason)
{
if(strchr(luser, '!'))
{
2002-09-13 16:30:05 +00:00
if (!IsServer(source_p))
2002-08-13 14:34:25 +00:00
sendto_one(source_p, ":%s NOTICE %s :Invalid character '!' in gline",
me.name, source_p->name);
return 1;
}
return 0;
}
/*
* set_local_gline
*
* inputs - pointer to oper nick
* - pointer to oper username
* - pointer to oper host
* - pointer to oper server
* - pointer to victim user
* - pointer to victim host
* - pointer reason
* output - NONE
* side effects -
*/
static void
set_local_gline(const char *oper_nick,
2002-08-13 14:34:25 +00:00
const char *oper_user,
const char *oper_host,
const char *oper_server,
const char *user,
const char *host,
2002-09-22 03:36:42 +00:00
unsigned long bantime,
2002-08-13 14:34:25 +00:00
const char *reason)
{
char buffer[IRCD_BUFSIZE];
struct ConfItem *aconf;
const char *current_date;
current_date = smalldate((time_t) 0);
aconf = make_conf();
aconf->status = CONF_KILL;
DupString(aconf->host, host);
2002-09-23 03:30:25 +00:00
if (reason != NULL)
ircsprintf(buffer, "%s (%s)",reason,current_date);
else
ircsprintf(buffer, "No Reason (%s)", current_date);
2002-08-13 14:34:25 +00:00
DupString(aconf->passwd, buffer);
DupString(aconf->name, (char *)user);
DupString(aconf->host, (char *)host);
2002-09-22 03:36:42 +00:00
aconf->hold = bantime;
2002-08-13 14:34:25 +00:00
add_gline(aconf);
check_klines();
}
/*
* log_gline()
*
*/
static void
log_gline(const char *oper_nick, const char *oper_user, const char *oper_host,
const char *oper_server, const char *user, const char *host,
2002-09-22 03:36:42 +00:00
unsigned long bantime, const char *reason)
2002-08-13 14:34:25 +00:00
{
char buffer[2*BUFSIZE];
char filenamebuf[PATH_MAX + 1];
static char timebuffer[MAX_DATE_STRING + 1];
struct tm* tmptr;
FBFILE *out;
if(ConfigFileEntry.glinefile == NULL)
{
sendto_realops_flags(FLAGS_ALL, L_ALL,"*** Problem opening glinefile.");
return;
}
ircsprintf(filenamebuf, "%s.%s",
ConfigFileEntry.glinefile, small_file_date((time_t) 0));
if ((out = fbopen(filenamebuf, "a")) == NULL)
{
sendto_realops_flags(FLAGS_ALL, L_ALL,
"*** Problem opening %s",filenamebuf);
2002-08-13 14:34:25 +00:00
return;
}
tmptr = localtime((const time_t*)&CurrentTime);
strftime(timebuffer, MAX_DATE_STRING, "%Y/%m/%d %H:%M:%S", tmptr);
ircsprintf(buffer,"#Gline for %s@%s %s added by the following\n",
user,host,timebuffer);
if (fbputs(buffer,out) == -1)
{
sendto_realops_flags(FLAGS_ALL, L_ALL,
"*** Problem writing to %s",filenamebuf);
2002-08-13 14:34:25 +00:00
fbclose(out);
return;
}
2002-09-22 03:36:42 +00:00
ircsprintf(buffer, "#%s!%s@%s on %s for %lu [%s]\n",
2002-08-13 14:34:25 +00:00
oper_nick,
oper_user,
oper_host,
oper_server,
2002-09-22 03:36:42 +00:00
bantime,
2002-08-13 14:34:25 +00:00
(reason)?reason:"No reason");
if (fbputs(buffer,out) == -1)
{
sendto_realops_flags(FLAGS_ALL, L_ALL,"*** Problem writing to %s",filenamebuf);
fbclose(out);
return;
}
ircsprintf(buffer, "\"%s\",\"%s\",\"%s %s\",\"%s\",%lu\n",
user,
host,
reason,
timebuffer,
oper_nick,
(unsigned long) CurrentTime);
if (fbputs(buffer,out) == -1)
{
sendto_realops_flags(FLAGS_ALL, L_ALL,"*** Problem writing to %s",filenamebuf);
fbclose(out);
return;
}
fbclose(out);
}
/*
** m_ungline
** added May 29th 2000 by Toby Verrall <toot@melnet.co.uk>
** added to hybrid-7 7/11/2000 --is
**
** parv[0] = sender nick
** parv[1] = gline to remove
*/
static void mo_ungline(struct Client *client_p, struct Client *source_p,
int parc,char *parv[])
2002-08-13 14:34:25 +00:00
{
char *user,*host;
2002-08-13 14:34:25 +00:00
if (!ConfigFileEntry.glines)
{
sendto_one(source_p,":%s NOTICE %s :UNGLINE disabled",me.name,parv[0]);
return;
}
2002-08-13 14:34:25 +00:00
if (!IsOperUnkline(source_p) || !IsOperGline(source_p))
2002-08-13 14:34:25 +00:00
{
sendto_one(source_p,":%s NOTICE %s :You need unkline = yes;",
me.name,parv[0]);
return;
2002-08-13 14:34:25 +00:00
}
if ( (host = strchr(parv[1], '@')) || *parv[1] == '*' )
2002-08-13 14:34:25 +00:00
{
/* Explicit user@host mask given */
2002-08-13 14:34:25 +00:00
if(host) /* Found user@host */
2002-08-13 14:34:25 +00:00
{
user = parv[1]; /* here is user part */
*(host++) = '\0'; /* and now here is host */
}
else
{
user = "*"; /* no @ found, assume its *@somehost */
host = parv[1];
2002-08-13 14:34:25 +00:00
}
}
else
{
sendto_one(source_p, ":%s NOTICE %s :Invalid parameters",
me.name, parv[0]);
return;
}
2002-08-13 14:34:25 +00:00
if(remove_gline_match(user, host))
{
sendto_one(source_p, ":%s NOTICE %s :Un-glined [%s@%s]",
me.name, parv[0],user, host);
2002-09-13 16:30:05 +00:00
sendto_server(NULL, NULL, NULL, NOCAPS, NOCAPS, NOFLAGS, ":%s UNGLINE %s@%s", source_p->name, user, host);
sendto_realops_flags(FLAGS_ALL, L_ALL,
"%s has removed the G-Line for: [%s@%s]",
get_oper_name(source_p), user, host );
ilog(L_NOTICE, "%s removed G-Line for [%s@%s]",
get_oper_name(source_p), user, host);
return;
}
else
{
sendto_one(source_p, ":%s NOTICE %s :No G-Line for %s@%s",
me.name, parv[0],user,host);
return;
}
}
2002-09-13 16:30:05 +00:00
/*
** ms_ungline
**
** parv[0] = sender nick
** parv[1] = gline to remove
*/
static void ms_ungline(struct Client *client_p, struct Client *source_p,
int parc,char *parv[])
{
char *user,*host;
if (!ConfigFileEntry.glines)
{
return;
}
if ( (host = strchr(parv[1], '@')) || *parv[1] == '*' )
{
/* Explicit user@host mask given */
if(host) /* Found user@host */
{
user = parv[1]; /* here is user part */
*(host++) = '\0'; /* and now here is host */
}
else
{
user = "*"; /* no @ found, assume its *@somehost */
host = parv[1];
}
}
else
{
return;
}
if(remove_gline_match(user, host))
{
sendto_realops_flags(FLAGS_ALL, L_ALL,
"%s has removed the G-Line for: [%s@%s]",
get_oper_name(source_p), user, host );
ilog(L_NOTICE, "%s removed G-Line for [%s@%s]",
get_oper_name(source_p), user, host);
return;
}
else
{
/* if its not on this server, just ignore it */
return;
}
}