Add m_searchkline

This commit is contained in:
Ed Kellett 2020-10-29 14:42:12 +00:00
parent dc468b5b19
commit 5a75a19bd2
No known key found for this signature in database
GPG key ID: CB9986DEF342FABC
2 changed files with 214 additions and 0 deletions

View file

@ -57,6 +57,7 @@ auto_load_mod_LTLIBRARIES = \
m_resv.la \
m_sasl.la \
m_scan.la \
m_searchkline.la \
m_services.la \
m_set.la \
m_signon.la \

213
modules/m_searchkline.c Normal file
View file

@ -0,0 +1,213 @@
/*
* Copyright (C) 2020 Ed Kellett
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
* USA
*/
#include <stdinc.h>
#include <send.h>
#include <client.h>
#include <modules.h>
#include <msg.h>
#include "hash.h"
#include <hostmask.h>
#include <numeric.h>
#include <s_conf.h>
#include <s_newconf.h>
#include <reject.h>
static const char searchkline_desc[] = "Provides the ability to search for K/D-lines";
static void mo_searchkline(struct MsgBuf *, struct Client *, struct Client *, int, const char **);
struct Message searchkline_msgtab = {
"SEARCHKLINE", 0, 0, 0, 0,
{mg_unreg, mg_not_oper, mg_ignore, mg_ignore, mg_ignore, {mo_searchkline, 2}}
};
mapi_clist_av1 searchkline_clist[] = { &searchkline_msgtab, NULL };
DECLARE_MODULE_AV2(searchkline, NULL, NULL, searchkline_clist, NULL, NULL, NULL, NULL, searchkline_desc);
static void
report_kdline(struct Client *client, int type, struct ConfItem *aconf)
{
char *puser, *phost, *reason, *operreason, *mask;
char userhost[BUFSIZE];
char reasonbuf[BUFSIZE];
char letter;
switch (type)
{
case CONF_KILL:
letter = 'K';
break;
case CONF_DLINE:
letter = 'D';
break;
}
get_printable_kline(client, aconf, &phost, &reason, &puser, &operreason);
if (operreason != NULL)
{
snprintf(reasonbuf, sizeof reasonbuf, "%s!%s", reason, operreason);
reason = reasonbuf;
}
if (!EmptyString(aconf->user))
{
snprintf(userhost, sizeof userhost, "%s@%s", puser, phost);
mask = userhost;
}
else
{
mask = phost;
}
sendto_one(client, form_str(RPL_TESTLINE),
me.name, client->name,
(aconf->flags & CONF_FLAGS_TEMPORARY) ? tolower(letter) : letter,
(aconf->flags & CONF_FLAGS_TEMPORARY) ?
(long) ((aconf->hold - rb_current_time()) / 60) : 0L,
mask, reason);
}
static bool
search_ip_kdlines(struct Client *client, const char *username, struct sockaddr *ip, int blen, int fam)
{
struct sockaddr_in ip4;
bool found = false;
struct AddressRec *arec;
int masktype = fam == AF_INET ? HM_IPV4 : HM_IPV6;
size_t i;
size_t min = 0;
size_t max = ARRAY_SIZE(atable);
if (fam == AF_INET && blen == 32)
{
min = max = hash_ipv4(ip, 32);
}
else if (fam == AF_INET6 && blen == 128)
{
min = max = hash_ipv6(ip, 128);
}
for (i = min; i < max; i++)
{
for (arec = atable[i]; arec; arec = arec->next)
{
if ((arec->type != CONF_DLINE && arec->type != CONF_KILL) ||
arec->masktype != masktype ||
arec->Mask.ipa.bits < blen ||
!comp_with_mask_sock(ip, (struct sockaddr *)&arec->Mask.ipa.addr, blen))
continue;
if (arec->type == CONF_KILL && !mask_match(username, arec->username))
continue;
report_kdline(client, arec->type, arec->aconf);
found = true;
}
}
if (fam == AF_INET6 && blen == 128 &&
rb_ipv4_from_ipv6((struct sockaddr_in6 *)ip, &ip4))
{
found = found || search_ip_kdlines(client, username, (struct sockaddr *)&ip4, 32, AF_INET);
}
return found;
}
static void
mo_searchkline(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
struct rb_sockaddr_storage ip;
const char *username = NULL;
const char *host = NULL;
char *mask;
char *p;
int blen;
int type;
bool found = false;
size_t i;
struct AddressRec *arec;
if (!HasPrivilege(source_p, "oper:testline"))
{
sendto_one(source_p, form_str(ERR_NOPRIVS),
me.name, source_p->name, "testline");
return;
}
mask = LOCAL_COPY(parv[1]);
if ((p = strchr(mask, '@')))
{
*p++ = '\0';
username = mask;
host = p;
if(EmptyString(host))
return;
}
else
{
host = mask;
}
if (username == NULL)
{
username = "*";
}
/* parses as an IP, check for IP bans */
if ((type = parse_netmask(host, &ip, &blen)) != HM_HOST)
{
if(type == HM_IPV6)
found = found || search_ip_kdlines(source_p, username, (struct sockaddr *)&ip, blen, AF_INET6);
else
found = found || search_ip_kdlines(source_p, username, (struct sockaddr *)&ip, blen, AF_INET);
}
/* all that's left is to check host-like K-lines */
for (i = 0; i < ARRAY_SIZE(atable); i++)
{
for (arec = atable[i]; arec; arec = arec->next)
{
if (arec->type != CONF_KILL ||
(type != HM_HOST && arec->masktype != HM_HOST) ||
!mask_match(host, arec->aconf->host) ||
!mask_match(username, arec->username))
continue;
report_kdline(source_p, arec->type, arec->aconf);
found = true;
}
}
if (found)
{
sendto_one(source_p, form_str(RPL_TESTLINE),
me.name, source_p->name,
'*', 0l, "*", "End of search results");
return;
}
sendto_one(source_p, form_str(RPL_NOTESTLINE),
me.name, source_p->name, parv[1]);
}