1
0
mirror of https://github.com/unrealircd/unrealircd.git synced 2026-07-02 10:06:39 +02:00
Files
unrealircd/src/s_kline.c
T

666 lines
14 KiB
C

/*
* Unreal Internet Relay Chat Daemon, src/s_kline.c
* (C) 1999-2000 Carsten Munk (Techie/Stskeeps) <stskeeps@tspre.org>
* File to take care of dynamic K:/G:/Z: lines
*
*
* See file AUTHORS in IRC package for additional names of
* the programmers.
*
* 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "struct.h"
#include "common.h"
#include "sys.h"
#include "numeric.h"
#include "msg.h"
#include "channel.h"
#include <time.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef _WIN32
#include <io.h>
#endif
#include <fcntl.h>
#include "h.h"
aTKline *tklines = NULL;
#define AllocCpy(x,y) x = (char *) MyMalloc(strlen(y) + 1); strcpy(x,y)
#define GFreeStr(x) MyFree((char *) x)
#define GFreeGline(x) MyFree((aGline *) x)
extern char zlinebuf[];
/*
* type = TKL_*
* usermask@hostmask
* reason
* setby = whom set it
* expire_at = when to expire - 0 if not to expire
* set_at = was set at
*/
int tkl_add_line(int type, char *usermask, char *hostmask, char *reason, char *setby, TS expire_at, TS set_at)
{
aTKline *nl;
nl = (aTKline *) MyMalloc(sizeof(aTKline));
if (!nl)
return -1;
nl->type = type;
nl->expire_at = expire_at;
nl->set_at = set_at;
AllocCpy(nl->usermask, usermask);
AllocCpy(nl->hostmask, hostmask);
AllocCpy(nl->reason, reason);
AllocCpy(nl->setby, setby);
AddListItem(nl, tklines);
}
aTKline *tkl_del_line(aTKline *tkl)
{
aTKline *p, *q;
for (p = tklines; p; p = p->next)
{
if (p == tkl)
{
q = p->next;
GFreeStr(p->hostmask);
GFreeStr(p->usermask);
GFreeStr(p->reason);
GFreeStr(p->setby);
DelListItem(p, tklines);
MyFree((aTKline *) p);
return q;
}
}
return NULL;
}
aTKline *tkl_expire(aTKline * tmp)
{
char whattype[512];
long i, i1;
char *chost, *cname, *cip;
int is_ip;
aClient *acptr;
if (!tmp)
return NULL;
whattype[0] = 0;
if ((tmp->expire_at == 0) || (tmp->expire_at > TStime()))
{
sendto_ops
("tkl_expire(): expire for not-yet-expired tkline %s@%s",
tmp->usermask, tmp->hostmask);
return (tmp->next);
}
if (tmp->type & TKL_GLOBAL)
{
if (tmp->type & TKL_KILL)
{
strcpy(whattype, "G:Line");
}
else if (tmp->type & TKL_ZAP)
{
strcpy(whattype, "Global Z:Line");
}
else if (tmp->type & TKL_SHUN)
strcpy(whattype, "Shun");
}
else
{
if (tmp->type & TKL_KILL)
{
strcpy(whattype, "Timed K:Line");
}
else if (tmp->type & TKL_ZAP)
{
strcpy(whattype, "Timed Z:Line");
}
else if (tmp->type & TKL_SHUN)
strcpy(whattype, "Local Shun");
}
sendto_snomask(SNO_TKL,
"*** Expiring %s (%s@%s) made by %s (Reason: %s) set %li seconds ago",
whattype, tmp->usermask, tmp->hostmask, tmp->setby, tmp->reason,
TStime() - tmp->set_at);
ircd_log
(LOG_TKL, "Expiring %s (%s@%s) made by %s (Reason: %s) set %li seconds ago",
whattype, tmp->usermask, tmp->hostmask, tmp->setby, tmp->reason,
TStime() - tmp->set_at);
if (tmp->type & TKL_SHUN)
{
for (i1 = 0; i1 <= 5; i1++)
{
/* winlocal
for (i = 0; i <= (MAXCONNECTIONS - 1); i++)
*/
for (i = 0; i <= LastSlot; ++i)
{
if (acptr = local[i])
if (MyClient(acptr) && IsShunned(acptr))
{
chost = acptr->sockhost;
cname = acptr->user->username;
cip = (char *)Inet_ia2p(&acptr->ip);
if (!(*tmp->hostmask < '0') && (*tmp->hostmask > '9'))
is_ip = 1;
else
is_ip = 0;
if (is_ip ==
0 ? (!match(tmp->hostmask,
chost)
&& !match(tmp->usermask,
cname)) : (!match(tmp->
hostmask, chost)
|| !match(tmp->hostmask,
cip))
&& !match(tmp->usermask,
cname))
{
ClearShunned(acptr);
#ifdef SHUN_NOTICES
sendto_one(acptr,
":%s NOTICE %s :*** You are no longer shunned",
me.name,
acptr->name);
#endif
}
}
}
}
}
return (tkl_del_line(tmp));
}
EVENT(tkl_check_expire)
{
aTKline *gp, t;
TS nowtime;
nowtime = TStime();
for (gp = tklines; gp; gp = gp->next)
{
if (gp->expire_at <= nowtime && !(gp->expire_at == 0))
{
t.next = tkl_expire(gp);
gp = &t;
}
}
}
/*
returns -1 if no tkline found
returns >= 0 if client exits
*/
int find_tkline_match(aClient *cptr, int xx)
{
aTKline *lp;
char *chost, *cname, *cip;
TS nowtime;
int is_ip;
char msge[1024];
char gmt2[256];
int points = 0;
if (IsServer(cptr) || IsMe(cptr))
return -1;
nowtime = TStime();
chost = cptr->sockhost;
cname = cptr->user ? cptr->user->username : "unknown";
cip = (char *)Inet_ia2p(&cptr->ip);
for (lp = tklines; lp; lp = lp->next)
{
points = 0;
if (!match(lp->usermask, cname) && !match(lp->hostmask, chost))
points = 1;
if (!match(lp->usermask, cname) && !match(lp->hostmask, cip))
points = 1;
if (points == 1)
break;
else
points = 0;
}
if (points != 1)
return -1;
if ((lp->type & TKL_KILL) && (xx != 2))
{
if (lp->type & TKL_GLOBAL)
{
ircstp->is_ref++;
sendto_one(cptr,
":%s NOTICE %s :*** You are %s from %s (%s)",
me.name, cptr->name,
(lp->expire_at ? "banned" : "permanently banned"),
ircnetwork, lp->reason);
ircsprintf(msge, "User has been %s from %s (%s)",
(lp->expire_at ? "banned" : "permanently banned"),
ircnetwork, lp->reason);
return (exit_client(cptr, cptr, &me,
msge));
}
else
{
ircstp->is_ref++;
sendto_one(cptr,
":%s NOTICE %s :*** You are %s from %s (%s)",
me.name, cptr->name,
(lp->expire_at ? "banned" : "permanently banned"),
me.name, lp->reason);
ircsprintf(msge, "User is %s (%s)",
(lp->expire_at ? "banned" : "permanently banned"),
lp->reason);
return (exit_client(cptr, cptr, &me,
msge));
}
}
if (lp->type & TKL_ZAP)
{
ircstp->is_ref++;
ircsprintf(msge,
"Z:lined (%s)",lp->reason);
return exit_client(cptr, cptr, &me, msge);
}
if (lp->type & (TKL_SHUN))
{
if (IsShunned(cptr))
return -1;
if (IsAdmin(cptr))
return -1;
SetShunned(cptr);
return -1;
}
return -1;
}
int find_tkline_match_zap(aClient *cptr)
{
aTKline *lp;
char *cip;
TS nowtime;
char msge[1024];
if (IsServer(cptr) || IsMe(cptr))
return -1;
nowtime = TStime();
cip = (char *)Inet_ia2p(&cptr->ip);
for (lp = tklines; lp; lp = lp->next)
{
if (lp->type & TKL_ZAP)
{
if (!match(lp->hostmask, cip))
{
ircstp->is_ref++;
ircsprintf(msge,
"ERROR :Closing Link: [%s] Z:Lined (%s)\r\n",
#ifndef INET6
inetntoa((char *)&cptr->ip), lp->reason);
#else
inet_ntop(AF_INET6, (char *)&cptr->ip,
mydummy, MYDUMMY_SIZE));
#endif
strcpy(zlinebuf, msge);
return (1);
}
}
}
return -1;
}
int tkl_sweep()
{
/* just sweeps local for people that should be killed */
aClient *acptr;
long i;
tkl_check_expire(NULL);
for (i = 0; i <= (MAXCONNECTIONS - 1); i++)
{
if (acptr = local[i])
find_tkline_match(acptr, 0);
}
return 1;
}
void tkl_stats(aClient *cptr)
{
aTKline *tk;
TS curtime;
/*
We output in this row:
Glines,GZlines,KLine, ZLIne
Character:
G, Z, K, z
*/
if (!IsAnOper(cptr) && OPER_ONLY_STATS && (strchr(OPER_ONLY_STATS, 'G') || strchr(OPER_ONLY_STATS, 'g'))) {
sendto_one(cptr, err_str(ERR_NOPRIVILEGES), me.name, cptr->name);
return;
}
tkl_check_expire(NULL);
curtime = TStime();
for (tk = tklines; tk; tk = tk->next)
{
if (tk->type == (TKL_KILL | TKL_GLOBAL))
{
sendto_one(cptr, rpl_str(RPL_STATSGLINE), me.name,
cptr->name, 'G', tk->usermask, tk->hostmask,
(tk->expire_at !=
0) ? (tk->expire_at - curtime) : 0,
(curtime - tk->set_at), tk->setby, tk->reason);
}
if (tk->type == (TKL_ZAP | TKL_GLOBAL))
{
sendto_one(cptr, rpl_str(RPL_STATSGLINE), me.name,
cptr->name, 'Z', tk->usermask, tk->hostmask,
(tk->expire_at !=
0) ? (tk->expire_at - curtime) : 0,
(curtime - tk->set_at), tk->setby, tk->reason);
}
if (tk->type == (TKL_SHUN | TKL_GLOBAL))
{
sendto_one(cptr, rpl_str(RPL_STATSGLINE), me.name,
cptr->name, 's', tk->usermask, tk->hostmask,
(tk->expire_at !=
0) ? (tk->expire_at - curtime) : 0,
(curtime - tk->set_at), tk->setby, tk->reason);
}
if (tk->type == (TKL_KILL))
{
sendto_one(cptr, rpl_str(RPL_STATSGLINE), me.name,
cptr->name, 'K', tk->usermask, tk->hostmask,
(tk->expire_at !=
0) ? (tk->expire_at - curtime) : 0,
(curtime - tk->set_at), tk->setby, tk->reason);
}
if (tk->type == (TKL_ZAP))
{
sendto_one(cptr, rpl_str(RPL_STATSGLINE), me.name,
cptr->name, 'z', tk->usermask, tk->hostmask,
(tk->expire_at !=
0) ? (tk->expire_at - curtime) : 0,
(curtime - tk->set_at), tk->setby, tk->reason);
}
}
}
void tkl_synch(aClient *sptr)
{
aTKline *tk;
char typ;
for (tk = tklines; tk; tk = tk->next)
{
if (tk->type & TKL_GLOBAL)
{
if (tk->type & TKL_KILL)
typ = 'G';
if (tk->type & TKL_ZAP)
typ = 'Z';
if (tk->type & TKL_SHUN)
typ = 's';
sendto_one(sptr,
":%s %s + %c %s %s %s %li %li :%s", me.name,
IsToken(sptr) ? TOK_TKL : MSG_TKL,
typ,
tk->usermask, tk->hostmask, tk->setby,
tk->expire_at, tk->set_at, tk->reason);
}
}
}
/*
Service function for timed *:lines
add: TKL + type user host setby expire_at set_at reason
del: TKL - type user host removedby
list: TKL ?
only global lines are spread out this way.
type= G = G:Line
Z = Z:Line
*/
int m_tkl(aClient *cptr, aClient *sptr, int parc, char *parv[])
{
aTKline *tk;
int type;
int found = 0;
char gmt[256], gmt2[256];
char txt[256];
TS expiry_1, setat_1;
if (!IsServer(sptr) && !IsOper(sptr) && !IsMe(sptr))
return 0;
if (parc < 2)
return 0;
tkl_check_expire(NULL);
switch (*parv[1])
{
case '+':
{
/* we relay on servers to be failsafe.. */
if (!IsServer(sptr) && !IsMe(sptr))
return 0;
if (parc < 9)
return 0;
if (parv[2][0] == 'G')
type = TKL_KILL | TKL_GLOBAL;
else if (parv[2][0] == 'Z')
type = TKL_ZAP | TKL_GLOBAL;
else if (parv[2][0] == 'z')
type = TKL_ZAP;
else if (parv[2][0] == 'k')
type = TKL_KILL;
else if (parv[2][0] == 's')
type = TKL_SHUN | TKL_GLOBAL;
else
return 0;
found = 0;
for (tk = tklines; tk; tk = tk->next)
{
if (tk->type == type)
{
if (!strcmp(tk->hostmask, parv[4])
&& !strcmp(tk->usermask, parv[3]))
{
found = 1;
break;
}
}
}
/* G:Line already exists, don't add */
if (found == 1)
return 0;
expiry_1 = atol(parv[6]);
setat_1 = atol(parv[7]);
/* there is something fucked here? */
tkl_add_line(type, parv[3], parv[4], parv[8], parv[5],
expiry_1, setat_1);
strncpy(gmt, asctime(gmtime((TS *)&setat_1)), sizeof(gmt));
strncpy(gmt2, asctime(gmtime((TS *)&expiry_1)), sizeof(gmt2));
gmt[strlen(gmt) - 1] = '\0';
gmt2[strlen(gmt2) - 1] = '\0';
switch (type)
{
case TKL_KILL:
strcpy(txt, "Timed K:Line");
break;
case TKL_ZAP:
strcpy(txt, "Timed Z:Line");
break;
case TKL_KILL | TKL_GLOBAL:
strcpy(txt, "G:Line");
break;
case TKL_ZAP | TKL_GLOBAL:
strcpy(txt, "Global Z:line");
break;
case TKL_SHUN | TKL_GLOBAL:
strcpy(txt, "Shun");
break;
default:
strcpy(txt, "Unknown *:Line");
}
if (expiry_1 != 0)
{
sendto_snomask(SNO_TKL,
"*** %s added for %s@%s on %s GMT (from %s to expire at %s GMT: %s)",
txt, parv[3], parv[4], gmt, parv[5], gmt2,
parv[8]);
ircd_log
(LOG_TKL, "%s added for %s@%s on %s GMT (from %s to expire at %s GMT: %s)",
txt, parv[3], parv[4], gmt, parv[5], gmt2,
parv[8]);
}
else
{
sendto_snomask(SNO_TKL,
"*** Permanent %s added for %s@%s on %s GMT (from %s: %s)",
txt, parv[3], parv[4], gmt, parv[5], parv[8]);
ircd_log
(LOG_TKL, "Permanent %s added for %s@%s on %s GMT (from %s: %s)",
txt, parv[3], parv[4], gmt, parv[5], parv[8]);
}
loop.do_tkl_sweep = 1;
if (type & TKL_GLOBAL)
{
sendto_serv_butone(cptr,
":%s TKL %s %s %s %s %s %s %s :%s", sptr->name,
parv[1], parv[2], parv[3], parv[4], parv[5],
parv[6], parv[7], parv[8]);
}
return 0;
}
case '-':
if (!IsServer(sptr) && !IsMe(sptr))
return 0;
if (*parv[2] == 'G')
type = TKL_KILL | TKL_GLOBAL;
else if (*parv[2] == 'Z')
type = TKL_ZAP | TKL_GLOBAL;
else if (*parv[2] == 'z')
type = TKL_ZAP;
else if (*parv[2] == 'k')
type = TKL_KILL;
else if (*parv[2] == 's')
type = TKL_SHUN | TKL_GLOBAL;
else
return 0;
switch (type)
{
case TKL_KILL:
strcpy(txt, "Timed K:Line");
break;
case TKL_ZAP:
strcpy(txt, "Timed Z:Line");
break;
case TKL_KILL | TKL_GLOBAL:
strcpy(txt, "G:Line");
break;
case TKL_ZAP | TKL_GLOBAL:
strcpy(txt, "Global Z:line");
break;
case TKL_SHUN | TKL_GLOBAL:
strcpy(txt, "Shun");
break;
default:
strcpy(txt, "Unknown *:Line");
}
found = 0;
for (tk = tklines; tk; tk = tk->next)
{
if (tk->type == type)
{
if (!strcmp(tk->hostmask, parv[4])
&& !strcmp(tk->usermask, parv[3]))
{
strncpy(gmt,
asctime(gmtime((TS *)&tk->
set_at)), sizeof(gmt));
gmt[strlen(gmt) - 1] = '\0';
sendto_snomask(SNO_TKL,
"%s removed %s %s@%s (set at %s - reason: %s)",
parv[5], txt, tk->usermask,
tk->hostmask, gmt, tk->reason);
tkl_del_line(tk);
if (type & TKL_GLOBAL)
sendto_serv_butone(cptr,
":%s TKL %s %s %s %s %s",
sptr->name, parv[1],
parv[2], parv[3], parv[4],
parv[5]);
break;
}
}
}
break;
case '?':
if (IsAnOper(sptr))
tkl_stats(sptr);
}
}