Merge insp20

This commit is contained in:
Attila Molnar 2014-01-21 18:44:08 +01:00
commit e244cb2c63
48 changed files with 353 additions and 147 deletions

View File

@ -361,8 +361,8 @@ Sets your name to the specified name.">
<helpop key="coper" value="Oper Commands
-------------
OPERMOTD CHECK CLONES USERIP LINE
ALLTIME MODULES WALLOPS GLOBOPS
OPERMOTD CHECK CLONES USERIP TLINE
ALLTIME WALLOPS GLOBOPS
SETHOST SETIDENT CHGHOST CHGIDENT CHGNAME
SETIDLE SWHOIS

View File

@ -34,7 +34,7 @@ PRIVMSG NOTICE NICK JOIN PART
CYCLE KNOCK MODE DEVOICE TOPIC
KICK FPART REMOVE TBAN INVITE
UNINVITE AWAY DCCALLOW SILENCE ACCEPT
MKPASSWD VHOST TITLE
MKPASSWD VHOST TITLE SETNAME
WHOIS WHOWAS ISON USERHOST WATCH
LIST NAMES WHO MOTD
@ -49,11 +49,11 @@ OPER">
<helpop key="coper" value="Oper Commands
-------------
OPERMOTD CHECK TAXONOMY CLONES USERIP
TLINE ALLTIME MODULES WALLOPS GLOBOPS
OPERMOTD CHECK CLONES USERIP TLINE
ALLTIME WALLOPS GLOBOPS
SETHOST SETIDENT SETNAME CHGHOST CHGIDENT
CHGNAME SETIDLE SWHOIS
SETHOST SETIDENT CHGHOST CHGIDENT CHGNAME
SETIDLE SWHOIS
SANICK NICKLOCK NICKUNLOCK

View File

@ -236,7 +236,7 @@
<connect
# deny: Will not let people connect if they have specified host/IP.
deny="69.254.*">
deny="192.0.2.*">
# connect:reason is the message that users will see if they match a deny block
<connect deny="3ffe::0/32" reason="The 6bone address space is deprecated">
@ -253,7 +253,7 @@
parent="main"
# allow: What IP addresses/hosts to allow for this block.
allow="196.12.*"
allow="203.0.113.*"
# hash: what hash this password is hashed with. requires the module
# for selected hash (m_md5.so, m_sha256.so or m_ripemd160.so) be
@ -734,13 +734,15 @@
# no Do not show
operspywhois="no"
# runasuser: If this is set, InspIRCd will attempt to setuid
# to run as this user- allows binding of ports under 1024.
# runasuser: If this is set, InspIRCd will attempt to switch
# to run as this user, which allows binding of ports under 1024.
# You should NOT set this unless you are starting as root.
# NOT SUPPORTED/NEEDED UNDER WINDOWS.
#runasuser=""
# runasgroup: If this is set, InspIRCd will attempt to set group
# to run under this group, which allows binding of ports under 1024
# runasgroup: If this is set, InspIRCd will attempt to switch
# to run as this group, which allows binding of ports under 1024.
# You should NOT set this unless you are starting as root.
# NOT SUPPORTED/NEEDED UNDER WINDOWS.
#runasgroup=""
@ -894,7 +896,7 @@
<badip
# ipmask: IP range to ban. Wildcards and CIDR can be used.
ipmask="69.69.69.69"
ipmask="192.0.2.69"
# reason: Reason to display when user is disconnected.
reason="No porn here thanks.">
@ -913,22 +915,22 @@
<badhost
# host: ident@hostname to ban.
# Wildcards and CIDR (if you specify an IP) can be used.
host="*@hundredz.n.hundredz.o.1337.kiddies.com"
host="*@hundredz.n.hundredz.o.1337.kiddies.example.net"
# reason: Reason to display when user is disconnected
reason="Too many 1337 kiddiots">
<badhost host="root@*" reason="Don't irc as root!">
<badhost host="*@172.32.0.0/16" reason="This subnet is bad.">
<badhost host="root@*" reason="Don't IRC as root!">
<badhost host="*@198.51.100.0/24" reason="This subnet is bad.">
# exception: Hosts that are exempt from [kgz]lines.
<exception
# host: ident@hostname to exempt.
# Wildcards and CIDR (if you specify an IP) can be used.
host="*@ircop.host.com"
host="*@ircop.example.com"
# reason: Reason for exception. Only shown in /stats e
reason="Opers hostname">
reason="Oper's hostname">
#-#-#-#-#-#-#-#-#-#-#- INSANE BAN OPTIONS -#-#-#-#-#-#-#-#-#-#-#-#-#-#
# #

View File

@ -29,7 +29,7 @@
# allowmask: Range of IP addresses to allow for this link.
# Can be a CIDR (see example).
allowmask="69.58.44.0/24 127.0.0.0/8"
allowmask="203.0.113.0/24 127.0.0.0/8 2001:db8::/32"
# timeout: If defined, this option defines how long the server
# will wait to consider the connect attempt failed and try the
@ -74,7 +74,7 @@
<link name="hub.penguin.org"
ipaddr="penguin.box.com"
port="7000"
allowmask="69.58.44.0/24"
allowmask="203.0.113.0/24"
timeout="300"
ssl="gnutls"
bind="1.2.3.4"

View File

@ -842,6 +842,9 @@
# a <bind> tag with type "httpd", and load at least one of the other
# m_httpd_* modules to provide pages to display.
#
# You can adjust the timeout for HTTP connections below. All HTTP
# connections will be closed after (roughly) this many seconds.
#<httpd timeout="20">
#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
# http ACL module: Provides access control lists for m_httpd dependent
@ -1557,7 +1560,8 @@
#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
# SASL authentication module: Provides support for IRC Authentication
# Layer (aka: atheme SASL) via AUTHENTICATE.
# Layer via AUTHENTICATE. Note: You also need to have m_cap.so loaded
# for SASL to work.
#<module name="m_sasl.so">
#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
@ -1816,6 +1820,8 @@
# SVSHold module: Implements SVSHOLD. Like Q:Lines, but can only be #
# added/removed by Services. #
#<module name="m_svshold.so">
# If silent is true no snotices will be generated by SVSHOLD.
#<svshold silent="false">
#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
# SWHOIS module: Allows you to add arbitary lines to user WHOIS.

View File

@ -90,7 +90,7 @@
# Multiple options can be separated by spaces and CIDR's are allowed.
# You CAN use just * or *@* for this section, but it is not recommended
# for security reasons.
host="ident@dialup15.isp.com *@localhost *@server.com *@3ffe::0/16"
host="yourident@dialup15.isp.com *@localhost *@example.com *@2001:db8::/32"
# ** ADVANCED ** This option is disabled by default.
# fingerprint: When using the m_sslinfo module, you may specify
@ -127,7 +127,7 @@
<oper
name="Brain"
password="s3cret"
host="ident@dialup15.isp.com *@localhost *@server.com *@3ffe::0/16"
host="yourident@dialup15.isp.com *@localhost *@example.com *@2001:db8::/32"
#fingerprint="67cb9dc013248a829bb2171ed11becd4"
type="NetAdmin">
@ -155,7 +155,7 @@
# Multiple options can be separated by spaces and CIDR's are allowed.
# You CAN use just * or *@* for this section, but it is not recommended
# for security reasons.
host="ident@dialup15.isp.com *@localhost *@server.com *@3ffe::0/16"
host="yourident@dialup15.isp.com *@localhost *@example.com *@2001:db8::/32"
# type: What oper type this oline is. See the block above for list
# of types. NOTE: This is case-sensitive as well.

View File

@ -83,8 +83,7 @@ class CoreExport ConfigTag : public refcountbase
inline const std::vector<KeyVal>& getItems() const { return items; }
/** Create a new ConfigTag, giving access to the private KeyVal item list */
static ConfigTag* create(const std::string& Tag, const std::string& file, int line,
std::vector<KeyVal>*&items);
static ConfigTag* create(const std::string& Tag, const std::string& file, int line, std::vector<KeyVal>*& Items);
private:
ConfigTag(const std::string& Tag, const std::string& file, int line);
};

View File

@ -132,7 +132,7 @@ inline std::string ConvToStr(const bool in)
*/
inline std::string ConvToStr(char in)
{
return std::string(in,1);
return std::string(1, in);
}
/** Template function to convert any input type to std::string

View File

@ -24,14 +24,14 @@ use warnings FATAL => qw(all);
use make::utilities;
if (!module_installed("LWP::Simple"))
{
die "Your system is missing the LWP::Simple Perl module!";
}
BEGIN {
unless (module_installed("LWP::Simple")) {
die "Your system is missing the LWP::Simple Perl module!";
}
unless (module_installed("Crypt::SSLeay") || module_installed("IO::Socket::SSL")) {
die "Your system is missing the Crypt::SSLeay or IO::Socket::SSL Perl modules!";
}
if (!module_installed("Crypt::SSLeay") && !module_installed("IO::Socket::SSL"))
{
die "Your system is missing the Crypt::SSLeay or IO::Socket::SSL Perl modules!";
}
use File::Basename;
@ -56,15 +56,20 @@ sub parse_url;
# retrieve and parse entries from sources.list
sub parse_url {
my $src = shift;
chomp(my $src = shift);
return if $url_seen{$src};
$url_seen{$src}++;
my $doc = get($src);
die "Could not retrieve $_" unless defined $doc;
my $ua = LWP::UserAgent->new(ssl_opts => { verify_hostname => 0 });
my $response = $ua->get($src);
unless ($response->is_success) {
my $err = $response->message;
die "Could not retrieve $src: $err";
}
my $mod;
for (split /\n+/, $doc) {
for (split /\n+/, $response->decoded_content) {
s/^\s+//; # ignore whitespace at start
next if /^#/;
if (/^module (\S+) (\S+) (\S+)/) {
@ -257,7 +262,7 @@ sub resolve_deps {
}
}
my $action = $#ARGV > 0 ? lc shift @ARGV : 'help';
my $action = $#ARGV >= 0 ? lc shift @ARGV : 'help';
if ($action eq 'install') {
for my $mod (@ARGV) {

View File

@ -654,7 +654,8 @@ const char* Channel::ChanModes(bool showkey)
*/
void Channel::UserList(User *user)
{
if (this->IsModeSet(secretmode) && !this->HasUser(user) && !user->HasPrivPermission("channels/auspex"))
bool has_privs = user->HasPrivPermission("channels/auspex");
if (this->IsModeSet(secretmode) && !this->HasUser(user) && !has_privs)
{
user->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", this->name.c_str());
return;
@ -679,7 +680,7 @@ void Channel::UserList(User *user)
{
if (i->first->quitting)
continue;
if ((!has_user) && (i->first->IsModeSet(invisiblemode)))
if ((!has_user) && (i->first->IsModeSet(invisiblemode)) && (!has_privs))
{
/*
* user is +i, and source not on the channel, does not show

View File

@ -30,7 +30,12 @@ class CommandAdmin : public Command
public:
/** Constructor for admin.
*/
CommandAdmin(Module* parent) : Command(parent,"ADMIN",0,0) { syntax = "[<servername>]"; }
CommandAdmin(Module* parent) : Command(parent,"ADMIN",0,0)
{
Penalty = 2;
syntax = "[<servername>]";
}
/** Handle command.
* @param parameters The parameters to the comamnd
* @param pcnt The number of parameters passed to teh command

View File

@ -30,7 +30,11 @@ class CommandCommands : public Command
public:
/** Constructor for commands.
*/
CommandCommands ( Module* parent) : Command(parent,"COMMANDS",0,0) { }
CommandCommands(Module* parent) : Command(parent,"COMMANDS",0,0)
{
Penalty = 3;
}
/** Handle command.
* @param parameters The parameters to the comamnd
* @param pcnt The number of parameters passed to teh command

View File

@ -32,7 +32,12 @@ class CommandInfo : public Command
public:
/** Constructor for info.
*/
CommandInfo ( Module* parent) : Command(parent,"INFO") { syntax = "[<servermask>]"; }
CommandInfo(Module* parent) : Command(parent,"INFO")
{
Penalty = 4;
syntax = "[<servername>]";
}
/** Handle command.
* @param parameters The parameters to the comamnd
* @param pcnt The number of parameters passed to teh command

View File

@ -31,7 +31,12 @@ class CommandModules : public Command
public:
/** Constructor for modules.
*/
CommandModules ( Module* parent) : Command(parent,"MODULES",0,0) { syntax = "[server]"; }
CommandModules(Module* parent) : Command(parent,"MODULES",0,0)
{
Penalty = 4;
syntax = "[<servername>]";
}
/** Handle command.
* @param parameters The parameters to the comamnd
* @param pcnt The number of parameters passed to teh command
@ -74,7 +79,7 @@ CmdResult CommandModules::Handle (const std::vector<std::string>& parameters, Us
Module* m = i->second;
Version V = m->GetVersion();
if (user->HasPrivPermission("servers/auspex"))
if (IS_LOCAL(user) && user->HasPrivPermission("servers/auspex"))
{
std::string flags("SvcC");
int pos = 0;

View File

@ -80,7 +80,7 @@ void CommandWhois::SplitChanList(User* source, User* dest, const std::string& cl
{
std::string line;
std::ostringstream prefix;
std::string::size_type start, pos, length;
std::string::size_type start, pos;
prefix << dest->nick << " :";
line = prefix.str();
@ -88,23 +88,13 @@ void CommandWhois::SplitChanList(User* source, User* dest, const std::string& cl
for (start = 0; (pos = cl.find(' ', start)) != std::string::npos; start = pos+1)
{
length = (pos == std::string::npos) ? cl.length() : pos;
if (line.length() + namelen + length - start > 510)
if (line.length() + namelen + pos - start > 510)
{
ServerInstance->SendWhoisLine(source, dest, 319, line);
line = prefix.str();
}
if(pos == std::string::npos)
{
line.append(cl.substr(start, length - start));
break;
}
else
{
line.append(cl.substr(start, length - start + 1));
}
line.append(cl.substr(start, pos - start + 1));
}
if (line.length() != prefix.str().length())

View File

@ -499,10 +499,10 @@ std::string ConfigTag::getTagLocation()
return src_name + ":" + ConvToStr(src_line);
}
ConfigTag* ConfigTag::create(const std::string& Tag, const std::string& file, int line, std::vector<KeyVal>*&items)
ConfigTag* ConfigTag::create(const std::string& Tag, const std::string& file, int line, std::vector<KeyVal>*& Items)
{
ConfigTag* rv = new ConfigTag(Tag, file, line);
items = &rv->items;
Items = &rv->items;
return rv;
}

View File

@ -161,13 +161,20 @@ void InspIRCd::QuickExit(int status)
exit(status);
}
// Required for returning the proper value of EXIT_SUCCESS for the parent process
static void VoidSignalHandler(int signalreceived)
{
exit(0);
}
bool InspIRCd::DaemonSeed()
{
#ifdef _WIN32
std::cout << "InspIRCd Process ID: " << con_green << GetCurrentProcessId() << con_reset << std::endl;
return true;
#else
signal(SIGTERM, InspIRCd::QuickExit);
// Do not use QuickExit here: It will exit with status SIGTERM which would break e.g. daemon scripts
signal(SIGTERM, VoidSignalHandler);
int childpid = fork();
if (childpid < 0)
@ -570,7 +577,7 @@ InspIRCd::InspIRCd(int argc, char** argv) :
if (!g)
{
this->Logs->Log("STARTUP", LOG_DEFAULT, "getgrnam() failed (bad user?): %s", strerror(errno));
this->Logs->Log("STARTUP", LOG_DEFAULT, "getgrnam(%s) failed (wrong group?): %s", SetGroup.c_str(), strerror(errno));
this->QuickExit(0);
}
@ -578,7 +585,7 @@ InspIRCd::InspIRCd(int argc, char** argv) :
if (ret == -1)
{
this->Logs->Log("STARTUP", LOG_DEFAULT, "setgid() failed (bad user?): %s", strerror(errno));
this->Logs->Log("STARTUP", LOG_DEFAULT, "setgid() failed (wrong group?): %s", strerror(errno));
this->QuickExit(0);
}
}
@ -593,7 +600,7 @@ InspIRCd::InspIRCd(int argc, char** argv) :
if (!u)
{
this->Logs->Log("STARTUP", LOG_DEFAULT, "getpwnam() failed (bad user?): %s", strerror(errno));
this->Logs->Log("STARTUP", LOG_DEFAULT, "getpwnam(%s) failed (wrong user?): %s", SetUser.c_str(), strerror(errno));
this->QuickExit(0);
}
@ -601,7 +608,7 @@ InspIRCd::InspIRCd(int argc, char** argv) :
if (ret == -1)
{
this->Logs->Log("STARTUP", LOG_DEFAULT, "setuid() failed (bad user?): %s", strerror(errno));
this->Logs->Log("STARTUP", LOG_DEFAULT, "setuid() failed (wrong user?): %s", strerror(errno));
this->QuickExit(0);
}
}

View File

@ -207,7 +207,12 @@ PrefixMode::PrefixMode(Module* Creator, const std::string& Name, char ModeLetter
ModeAction PrefixMode::OnModeChange(User* source, User*, Channel* chan, std::string& parameter, bool adding)
{
User* target = ServerInstance->FindNick(parameter);
User* target;
if (IS_LOCAL(source))
target = ServerInstance->FindNickOnly(parameter);
else
target = ServerInstance->FindNick(parameter);
if (!target)
{
source->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", parameter.c_str());
@ -347,9 +352,16 @@ ModeAction ModeParser::TryMode(User* user, User* targetuser, Channel* chan, bool
void ModeParser::Process(const std::vector<std::string>& parameters, User* user, ModeProcessFlag flags)
{
std::string target = parameters[0];
const std::string& target = parameters[0];
Channel* targetchannel = ServerInstance->FindChan(target);
User* targetuser = ServerInstance->FindNick(target);
User* targetuser = NULL;
if (!targetchannel)
{
if (IS_LOCAL(user))
targetuser = ServerInstance->FindNickOnly(target);
else
targetuser = ServerInstance->FindNick(target);
}
ModeType type = targetchannel ? MODETYPE_CHANNEL : MODETYPE_USER;
LastParse.clear();

View File

@ -388,18 +388,23 @@ void ModuleManager::DoSafeUnload(Module* mod)
std::vector<reference<ExtensionItem> > items;
ServerInstance->Extensions.BeginUnregister(modfind->second, items);
/* Give the module a chance to tidy out all its metadata */
for (chan_hash::iterator c = ServerInstance->chanlist->begin(); c != ServerInstance->chanlist->end(); c++)
for (chan_hash::iterator c = ServerInstance->chanlist->begin(); c != ServerInstance->chanlist->end(); )
{
mod->OnCleanup(TYPE_CHANNEL,c->second);
c->second->doUnhookExtensions(items);
const UserMembList* users = c->second->GetUsers();
Channel* chan = c->second;
++c;
mod->OnCleanup(TYPE_CHANNEL, chan);
chan->doUnhookExtensions(items);
const UserMembList* users = chan->GetUsers();
for(UserMembCIter mi = users->begin(); mi != users->end(); mi++)
mi->second->doUnhookExtensions(items);
}
for (user_hash::iterator u = ServerInstance->Users->clientlist->begin(); u != ServerInstance->Users->clientlist->end(); u++)
for (user_hash::iterator u = ServerInstance->Users->clientlist->begin(); u != ServerInstance->Users->clientlist->end(); )
{
mod->OnCleanup(TYPE_USER,u->second);
u->second->doUnhookExtensions(items);
User* user = u->second;
// The module may quit the user (e.g. SSL mod unloading) and that will remove it from the container
++u;
mod->OnCleanup(TYPE_USER, user);
user->doUnhookExtensions(items);
}
for(char m='A'; m <= 'z'; m++)
{

View File

@ -310,11 +310,11 @@ class ModuleAlias : public Module
for (unsigned int i = 0; i < newline.length(); i++)
{
char c = newline[i];
if (c == '$')
if ((c == '$') && (i + 1 < newline.length()))
{
if (isdigit(newline[i+1]))
{
int len = (newline[i+2] == '-') ? 3 : 2;
int len = ((i + 2 < newline.length()) && (newline[i+2] == '-')) ? 3 : 2;
std::string var = newline.substr(i, len);
result.append(GetVar(var, original_line));
i += len - 1;

View File

@ -158,13 +158,18 @@ class CommandAccept : public Command
*/
typedef std::pair<User*, bool> ACCEPTAction;
static ACCEPTAction GetTargetAndAction(std::string& tok)
static ACCEPTAction GetTargetAndAction(std::string& tok, User* cmdfrom = NULL)
{
bool remove = (tok[0] == '-');
if ((remove) || (tok[0] == '+'))
tok.erase(tok.begin());
User* target = ServerInstance->FindNick(tok);
User* target;
if (!cmdfrom || !IS_LOCAL(cmdfrom))
target = ServerInstance->FindNick(tok);
else
target = ServerInstance->FindNickOnly(tok);
if ((!target) || (target->registered != REG_ALL) || (target->quitting) || (IS_SERVER(target)))
target = NULL;
@ -216,7 +221,7 @@ public:
}
std::string tok = parameters[0];
ACCEPTAction action = GetTargetAndAction(tok);
ACCEPTAction action = GetTargetAndAction(tok, user);
if (!action.first)
{
user->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", tok.c_str());
@ -248,7 +253,7 @@ public:
// Find the target
std::string targetstring = parameters[0];
ACCEPTAction action = GetTargetAndAction(targetstring);
ACCEPTAction action = GetTargetAndAction(targetstring, user);
if (!action.first)
// Target is a "*" or source is local and the target is a list of nicks
return ROUTE_LOCALONLY;

View File

@ -106,6 +106,12 @@ class ModuleChannelNames : public Module
ConfigTag* tag = ServerInstance->Config->ConfValue("channames");
std::string denyToken = tag->getString("denyrange");
std::string allowToken = tag->getString("allowrange");
if (!denyToken.compare(0, 2, "0-"))
denyToken[0] = '1';
if (!allowToken.compare(0, 2, "0-"))
allowToken[0] = '1';
allowedmap.set();
irc::portparser denyrange(denyToken, false);

View File

@ -225,6 +225,10 @@ class CommandDccallow : public Command
user->WriteNumeric(998, ": they will be removed from your DCCALLOW list.");
user->WriteNumeric(998, ": your DCCALLOW list will be deleted when you leave IRC.");
user->WriteNumeric(999, ":End of DCCALLOW HELP");
LocalUser* localuser = IS_LOCAL(user);
if (localuser)
localuser->CommandFloodPenalty += 4000;
}
void DisplayDCCAllowList(User* user)

View File

@ -142,7 +142,10 @@ class DNSBLResolver : public DNS::Request
ServerInstance->XLines->ApplyLines();
}
else
{
delete kl;
return;
}
break;
}
case DNSBLConfEntry::I_GLINE:
@ -157,7 +160,10 @@ class DNSBLResolver : public DNS::Request
ServerInstance->XLines->ApplyLines();
}
else
{
delete gl;
return;
}
break;
}
case DNSBLConfEntry::I_ZLINE:
@ -172,7 +178,10 @@ class DNSBLResolver : public DNS::Request
ServerInstance->XLines->ApplyLines();
}
else
{
delete zl;
return;
}
break;
}
case DNSBLConfEntry::I_UNKNOWN:

View File

@ -96,7 +96,6 @@ class CommandHelpop : public Command
class ModuleHelpop : public Module
{
std::string h_file;
CommandHelpop cmd;
Helpop ho;
@ -108,7 +107,7 @@ class ModuleHelpop : public Module
void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE
{
helpop_map.clear();
HelpopMap help;
ConfigTagList tags = ServerInstance->Config->ConfTags("helpop");
for(ConfigIter i = tags.first; i != tags.second; ++i)
@ -123,20 +122,21 @@ class ModuleHelpop : public Module
throw ModuleException("m_helpop: The key 'index' is reserved for internal purposes. Please remove it.");
}
helpop_map[key] = value;
help[key] = value;
}
if (helpop_map.find("start") == helpop_map.end())
if (help.find("start") == help.end())
{
// error!
throw ModuleException("m_helpop: Helpop file is missing important entry 'start'. Please check the example conf.");
}
else if (helpop_map.find("nohelp") == helpop_map.end())
else if (help.find("nohelp") == help.end())
{
// error!
throw ModuleException("m_helpop: Helpop file is missing important entry 'nohelp'. Please check the example conf.");
}
helpop_map.swap(help);
}
void OnWhois(User* src, User* dst) CXX11_OVERRIDE

View File

@ -30,6 +30,7 @@ class ModuleHttpServer;
static ModuleHttpServer* HttpModule;
static bool claimed;
static std::set<HttpServerSocket*> sockets;
/** HTTP socket states
*/
@ -56,8 +57,11 @@ class HttpServerSocket : public BufferedSocket
std::string http_version;
public:
const time_t createtime;
HttpServerSocket(int newfd, const std::string& IP, ListenSocket* via, irc::sockets::sockaddrs* client, irc::sockets::sockaddrs* server)
: BufferedSocket(newfd), ip(IP), postsize(0)
, createtime(ServerInstance->Time())
{
InternalState = HTTP_SERVE_WAIT_REQUEST;
@ -66,6 +70,11 @@ class HttpServerSocket : public BufferedSocket
GetIOHook()->OnStreamSocketAccept(this, client, server);
}
~HttpServerSocket()
{
sockets.erase(this);
}
void OnError(BufferedSocketError) CXX11_OVERRIDE
{
ServerInstance->GlobalCulls.AddItem(this);
@ -347,6 +356,7 @@ class ModuleHttpServer : public Module
{
std::vector<HttpServerSocket *> httpsocks;
HTTPdAPIImpl APIImpl;
unsigned int timeoutsec;
public:
ModuleHttpServer()
@ -359,6 +369,12 @@ class ModuleHttpServer : public Module
HttpModule = this;
}
void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE
{
ConfigTag* tag = ServerInstance->Config->ConfValue("httpd");
timeoutsec = tag->getInt("timeout");
}
ModResult OnAcceptConnection(int nfd, ListenSocket* from, irc::sockets::sockaddrs* client, irc::sockets::sockaddrs* server) CXX11_OVERRIDE
{
if (from->bind_tag->getString("type") != "httpd")
@ -366,19 +382,41 @@ class ModuleHttpServer : public Module
int port;
std::string incomingip;
irc::sockets::satoap(*client, incomingip, port);
new HttpServerSocket(nfd, incomingip, from, client, server);
sockets.insert(new HttpServerSocket(nfd, incomingip, from, client, server));
return MOD_RES_ALLOW;
}
~ModuleHttpServer()
void OnBackgroundTimer(time_t curtime) CXX11_OVERRIDE
{
for (size_t i = 0; i < httpsocks.size(); i++)
if (!timeoutsec)
return;
time_t oldest_allowed = curtime - timeoutsec;
for (std::set<HttpServerSocket*>::const_iterator i = sockets.begin(); i != sockets.end(); )
{
httpsocks[i]->cull();
delete httpsocks[i];
HttpServerSocket* sock = *i;
++i;
if (sock->createtime < oldest_allowed)
{
sock->cull();
delete sock;
}
}
}
CullResult cull() CXX11_OVERRIDE
{
std::set<HttpServerSocket*> local;
local.swap(sockets);
for (std::set<HttpServerSocket*>::const_iterator i = local.begin(); i != local.end(); ++i)
{
HttpServerSocket* sock = *i;
sock->cull();
delete sock;
}
return Module::cull();
}
Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides HTTP serving facilities to modules", VF_VENDOR);

View File

@ -52,7 +52,7 @@ class ModuleHttpStats : public Module
ret += it->second;
ret += ';';
}
else if (*x == 0x9 || *x == 0xA || *x == 0xD || *x >= 0x20)
else if (*x == 0x09 || *x == 0x0A || *x == 0x0D || ((*x >= 0x20) && (*x <= 0x7e)))
{
// The XML specification defines the following characters as valid inside an XML document:
// Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]

View File

@ -336,7 +336,7 @@ class ModuleIdent : public Module
/* wooo, got a result (it will be good, or bad) */
if (isock->result.empty())
{
user->ident.insert(0, 1, '~');
user->ident.insert(user->ident.begin(), 1, '~');
user->WriteNotice("*** Could not find your ident, using " + user->ident + " instead.");
}
else

View File

@ -124,12 +124,8 @@ class JoinFlood : public ModeHandler
if (!channel->IsModeSet(this))
return MODEACTION_DENY;
joinfloodsettings* f = ext.get(channel);
if (f)
{
ext.unset(channel);
return MODEACTION_ALLOW;
}
ext.unset(channel);
return MODEACTION_ALLOW;
}
return MODEACTION_DENY;
}
@ -168,7 +164,7 @@ class ModuleJoinFlood : public Module
joinfloodsettings *f = jf.ext.get(memb->chan);
/* But all others are OK */
if (f)
if ((f) && (!f->islocked()))
{
f->addjoin();
if (f->shouldlock())

View File

@ -31,12 +31,7 @@ public:
return Version("Implements the ability to have server-side MLOCK enforcement.", VF_VENDOR);
}
void Prioritize()
{
ServerInstance->Modules->SetPriority(this, I_OnPreMode, PRIORITY_FIRST);
}
ModResult OnPreMode(User* source, User* dest, Channel* channel, const std::vector<std::string>& parameters) CXX11_OVERRIDE
ModResult OnRawMode(User* source, Channel* channel, const char mode, const std::string& parameter, bool adding, int pcnt)
{
if (!channel)
return MOD_RES_PASSTHRU;
@ -48,11 +43,11 @@ public:
if (!mlock_str)
return MOD_RES_PASSTHRU;
std::string::size_type p = parameters[1].find_first_of(*mlock_str);
std::string::size_type p = mlock_str->find(mode);
if (p != std::string::npos)
{
source->WriteNumeric(742, "%s %c %s :MODE cannot be set due to channel having an active MLOCK restriction policy",
channel->name.c_str(), parameters[1][p], mlock_str->c_str());
channel->name.c_str(), mode, mlock_str->c_str());
return MOD_RES_DENY;
}

View File

@ -35,6 +35,20 @@ class ModuleOverride : public Module
ChanModeReference key;
ChanModeReference limit;
static bool IsOverride(unsigned int userlevel, const std::string& modeline)
{
for (std::string::const_iterator i = modeline.begin(); i != modeline.end(); ++i)
{
ModeHandler* mh = ServerInstance->Modes->FindMode(*i, MODETYPE_CHANNEL);
if (!mh)
continue;
if (mh->GetLevelRequired() > userlevel)
return true;
}
return false;
}
public:
ModuleOverride()
: topiclock(this, "topiclock")
@ -110,7 +124,10 @@ class ModuleOverride : public Module
unsigned int mode = channel->GetPrefixValue(source);
if (mode < HALFOP_VALUE && CanOverride(source, "MODE"))
if (!IsOverride(mode, parameters[1]))
return MOD_RES_PASSTHRU;
if (CanOverride(source, "MODE"))
{
std::string msg = source->nick+" overriding modes:";
for(unsigned int i=0; i < parameters.size(); i++)

View File

@ -165,10 +165,12 @@ class ModulePermanentChannels : public Module
{
PermChannel p;
bool dirty;
bool loaded;
bool save_listmodes;
public:
ModulePermanentChannels() : p(this), dirty(false)
ModulePermanentChannels()
: p(this), dirty(false), loaded(false)
{
}
@ -301,8 +303,6 @@ public:
// to be able to set the modes they provide (e.g.: m_stripcolor is inited after us)
// Prioritize() is called after all module initialization is complete, consequently
// all modes are available now
static bool loaded = false;
if (loaded)
return;

View File

@ -60,7 +60,10 @@ class RemoveBase : public Command
const std::string& username = parameters[neworder ? 1 : 0];
/* Look up the user we're meant to be removing from the channel */
target = ServerInstance->FindNick(username);
if (IS_LOCAL(user))
target = ServerInstance->FindNickOnly(username);
else
target = ServerInstance->FindNick(username);
/* And the channel we're meant to be removing them from */
channel = ServerInstance->FindChan(channame);

View File

@ -149,6 +149,9 @@ typedef uint32_t dword;
class RIProv : public HashProvider
{
/** Final hash value
*/
byte hashcode[RMDsize/8];
void MDinit(dword *MDbuf, unsigned int* key)
{
@ -403,7 +406,6 @@ class RIProv : public HashProvider
byte *RMD(byte *message, dword length, unsigned int* key)
{
dword MDbuf[RMDsize/32]; /* contains (A, B, C, D(E)) */
static byte hashcode[RMDsize/8]; /* for final hash-value */
dword X[16]; /* current 16-word chunk */
unsigned int i; /* counter */
dword nbytes; /* # of bytes not yet processed */

View File

@ -60,7 +60,7 @@ class CommandSajoin : public Command
Channel* n = Channel::JoinUser(localuser, parameters[1], true);
if (n && n->HasUser(dest))
{
ServerInstance->SNO->WriteToSnoMask('a', user->nick+" used SAJOIN to make "+dest->nick+" join "+parameters[1]);
ServerInstance->SNO->WriteGlobalSno('a', user->nick+" used SAJOIN to make "+dest->nick+" join "+parameters[1]);
return CMD_SUCCESS;
}
else
@ -71,7 +71,6 @@ class CommandSajoin : public Command
}
else
{
ServerInstance->SNO->WriteToSnoMask('a', user->nick+" sent remote SAJOIN to make "+dest->nick+" join "+parameters[1]);
return CMD_SUCCESS;
}
}

View File

@ -91,20 +91,23 @@ class SaslAuthenticator
{
case SASL_INIT:
this->agent = msg[0];
this->user->Write("AUTHENTICATE %s", msg[3].c_str());
this->state = SASL_COMM;
break;
/* fall through */
case SASL_COMM:
if (msg[0] != this->agent)
return this->state;
if (msg[2] != "D")
if (msg[2] == "C")
this->user->Write("AUTHENTICATE %s", msg[3].c_str());
else
else if (msg[2] == "D")
{
this->state = SASL_DONE;
this->result = this->GetSaslResult(msg[3]);
}
else if (msg[2] == "M")
this->user->WriteNumeric(908, "%s %s :are available SASL mechanisms", this->user->nick.c_str(), msg[3].c_str());
else
ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, "Services sent an unknown SASL message \"%s\" \"%s\"", msg[2].c_str(), msg[3].c_str());
break;
case SASL_DONE:

View File

@ -102,6 +102,24 @@ class AChannel_M : public SimpleChannelModeHandler
AChannel_M(Module* Creator) : SimpleChannelModeHandler(Creator, "regmoderated", 'M') { }
};
static bool ReadCGIIRCExt(const char* extname, User* user, const std::string*& out)
{
ExtensionItem* wiext = ServerInstance->Extensions.GetItem(extname);
if (!wiext)
return false;
if (wiext->creator->ModuleSourceFile != "m_cgiirc.so")
return false;
StringExtItem* stringext = static_cast<StringExtItem*>(wiext);
std::string* addr = stringext->get(user);
if (!addr)
return false;
out = addr;
return true;
}
class AccountExtItemImpl : public AccountExtItem
{
public:
@ -121,8 +139,19 @@ class AccountExtItemImpl : public AccountExtItem
{
// Logged in
if (IS_LOCAL(user))
user->WriteNumeric(900, "%s %s :You are now logged in as %s",
user->GetFullHost().c_str(), value.c_str(), value.c_str());
{
const std::string* host = &user->dhost;
if (user->registered != REG_ALL)
{
if (!ReadCGIIRCExt("cgiirc_webirc_hostname", user, host))
{
ReadCGIIRCExt("cgiirc_webirc_ip", user, host);
}
}
user->WriteNumeric(900, "%s!%s@%s %s :You are now logged in as %s",
user->nick.c_str(), user->ident.c_str(), host->c_str(), value.c_str(), value.c_str());
}
AccountEvent(creator, user, value).Send();
}
@ -142,6 +171,7 @@ class ModuleServicesAccount : public Module
Channel_r m4;
User_r m5;
AccountExtItemImpl accountname;
bool checking_ban;
public:
ModuleServicesAccount() : m1(this), m2(this), m3(this), m4(this), m5(this),
accountname(this)
@ -219,8 +249,7 @@ class ModuleServicesAccount : public Module
ModResult OnCheckBan(User* user, Channel* chan, const std::string& mask) CXX11_OVERRIDE
{
static bool checking = false;
if (checking)
if (checking_ban)
return MOD_RES_PASSTHRU;
if ((mask.length() > 2) && (mask[1] == ':'))
@ -240,9 +269,9 @@ class ModuleServicesAccount : public Module
/* If we made it this far we know the user isn't registered
so just deny if it matches */
checking = true;
checking_ban = true;
bool result = chan->CheckBan(user, mask.substr(2));
checking = false;
checking_ban = false;
if (result)
return MOD_RES_DENY;

View File

@ -42,7 +42,7 @@ class SeeWhois : public SimpleUserModeHandler
class WhoisNoticeCmd : public Command
{
public:
WhoisNoticeCmd(Module* Creator) : Command(Creator,"WHOISNOTICE", 1)
WhoisNoticeCmd(Module* Creator) : Command(Creator,"WHOISNOTICE", 2)
{
flags_needed = FLAG_SERVERONLY;
}

View File

@ -85,7 +85,7 @@ class CommandSVSSilence : public Command
if (IS_LOCAL(u))
{
ServerInstance->Parser->CallHandler("SILENCE", std::vector<std::string>(++parameters.begin(), parameters.end()), u);
ServerInstance->Parser->CallHandler("SILENCE", std::vector<std::string>(parameters.begin() + 1, parameters.end()), u);
}
return CMD_SUCCESS;
@ -301,7 +301,7 @@ class ModuleSilence : public Module
void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE
{
maxsilence = ServerInstance->Config->ConfValue("showwhois")->getInt("maxentries", 32);
maxsilence = ServerInstance->Config->ConfValue("silence")->getInt("maxentries", 32);
if (!maxsilence)
maxsilence = 32;
}

View File

@ -38,6 +38,7 @@
ModuleSpanningTree::ModuleSpanningTree()
: rconnect(this), rsquit(this), map(this)
, commands(NULL), DNS(this, "DNS")
, KeepNickTS(false)
{
}
@ -246,7 +247,7 @@ void ModuleSpanningTree::ConnectServer(Link* x, Autoconnect* y)
{
bool ipvalid = true;
if (InspIRCd::Match(ServerInstance->Config->ServerName, assign(x->Name)))
if (InspIRCd::Match(ServerInstance->Config->ServerName, assign(x->Name), rfc_case_insensitive_map))
{
ServerInstance->SNO->WriteToSnoMask('l', "CONNECT: Not connecting to myself.");
return;
@ -377,9 +378,9 @@ ModResult ModuleSpanningTree::HandleConnect(const std::vector<std::string>& para
for (std::vector<reference<Link> >::iterator i = Utils->LinkBlocks.begin(); i < Utils->LinkBlocks.end(); i++)
{
Link* x = *i;
if (InspIRCd::Match(x->Name.c_str(),parameters[0]))
if (InspIRCd::Match(x->Name.c_str(),parameters[0], rfc_case_insensitive_map))
{
if (InspIRCd::Match(ServerInstance->Config->ServerName, assign(x->Name)))
if (InspIRCd::Match(ServerInstance->Config->ServerName, assign(x->Name), rfc_case_insensitive_map))
{
RemoteMessage(user, "*** CONNECT: Server \002%s\002 is ME, not connecting.",x->Name.c_str());
return MOD_RES_DENY;
@ -529,7 +530,7 @@ void ModuleSpanningTree::OnChangeName(User* user, const std::string &gecos)
if (user->registered != REG_ALL || !IS_LOCAL(user))
return;
CmdBuilder(user, "FNAME").push(gecos).Broadcast();
CmdBuilder(user, "FNAME").push_last(gecos).Broadcast();
}
void ModuleSpanningTree::OnChangeIdent(User* user, const std::string &ident)
@ -587,11 +588,12 @@ void ModuleSpanningTree::OnUserPostNick(User* user, const std::string &oldnick)
/** IMPORTANT: We don't update the TS if the oldnick is just a case change of the newnick!
*/
if (irc::string(user->nick.c_str()) != assign(oldnick))
if ((irc::string(user->nick.c_str()) != assign(oldnick)) && (!this->KeepNickTS))
user->age = ServerInstance->Time();
params.push_back(ConvToStr(user->age));
params.Broadcast();
this->KeepNickTS = false;
}
else if (!loopCall && user->nick == user->uuid)
{

View File

@ -77,6 +77,11 @@ class ModuleSpanningTree : public Module
*/
bool SplitInProgress;
/** If true OnUserPostNick() won't update the nick TS before sending the NICK,
* used when handling SVSNICK.
*/
bool KeepNickTS;
/** Constructor
*/
ModuleSpanningTree();

View File

@ -20,6 +20,7 @@
#include "inspircd.h"
#include "main.h"
#include "commands.h"
CmdResult CommandSVSNick::Handle(User* user, std::vector<std::string>& parameters)
@ -32,17 +33,28 @@ CmdResult CommandSVSNick::Handle(User* user, std::vector<std::string>& parameter
if (isdigit(nick[0]))
nick = u->uuid;
// Don't update the TS if the nick is exactly the same
if (u->nick == nick)
return CMD_FAILURE;
time_t NickTS = ConvToInt(parameters[2]);
if (NickTS <= 0)
return CMD_FAILURE;
ModuleSpanningTree* st = (ModuleSpanningTree*)(Module*)creator;
st->KeepNickTS = true;
u->age = NickTS;
if (!u->ForceNickChange(nick))
{
/* buh. UID them */
if (!u->ForceNickChange(u->uuid))
{
ServerInstance->Users->QuitUser(u, "Nickname collision");
return CMD_SUCCESS;
}
}
u->age = ConvToInt(parameters[2]);
st->KeepNickTS = false;
}
return CMD_SUCCESS;

View File

@ -363,7 +363,7 @@ Link* SpanningTreeUtilities::FindLink(const std::string& name)
for (std::vector<reference<Link> >::iterator i = LinkBlocks.begin(); i != LinkBlocks.end(); ++i)
{
Link* x = *i;
if (InspIRCd::Match(x->Name.c_str(), name.c_str()))
if (InspIRCd::Match(x->Name.c_str(), name.c_str(), rfc_case_insensitive_map))
{
return x;
}

View File

@ -23,6 +23,11 @@
#include "inspircd.h"
#include "xline.h"
namespace
{
bool silent;
}
/** Holds a SVSHold item
*/
class SVSHold : public XLine
@ -48,6 +53,15 @@ public:
return InspIRCd::Match(s, nickname);
}
void DisplayExpiry()
{
if (!silent)
{
ServerInstance->SNO->WriteToSnoMask('x', "Removing expired SVSHOLD %s (set by %s %ld seconds ago)",
nickname.c_str(), source.c_str(), (long)(ServerInstance->Time() - set_time));
}
}
const std::string& Displayable()
{
return nickname;
@ -99,7 +113,8 @@ class CommandSvshold : public Command
{
if (ServerInstance->XLines->DelLine(parameters[0].c_str(), "SVSHOLD", user))
{
ServerInstance->SNO->WriteToSnoMask('x',"%s removed SVSHOLD on %s",user->nick.c_str(),parameters[0].c_str());
if (!silent)
ServerInstance->SNO->WriteToSnoMask('x',"%s removed SVSHOLD on %s",user->nick.c_str(),parameters[0].c_str());
}
else
{
@ -116,6 +131,9 @@ class CommandSvshold : public Command
if (ServerInstance->XLines->AddLine(r, user))
{
if (silent)
return CMD_SUCCESS;
if (!duration)
{
ServerInstance->SNO->WriteGlobalSno('x', "%s added permanent SVSHOLD for %s: %s", user->nick.c_str(), parameters[0].c_str(), parameters[2].c_str());
@ -159,6 +177,12 @@ class ModuleSVSHold : public Module
ServerInstance->XLines->RegisterFactory(&s);
}
void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE
{
ConfigTag* tag = ServerInstance->Config->ConfValue("svshold");
silent = tag->getBool("silent");
}
ModResult OnStats(char symbol, User* user, string_list &out) CXX11_OVERRIDE
{
if(symbol != 'S')

View File

@ -35,7 +35,12 @@ class CommandUninvite : public Command
CmdResult Handle (const std::vector<std::string> &parameters, User *user)
{
User* u = ServerInstance->FindNick(parameters[0]);
User* u;
if (IS_LOCAL(user))
u = ServerInstance->FindNickOnly(parameters[0]);
else
u = ServerInstance->FindNick(parameters[0]);
Channel* c = ServerInstance->FindChan(parameters[1]);
if ((!c) || (!u) || (u->registered != REG_ALL))

View File

@ -40,7 +40,7 @@ class CommandUserip : public Command
for (int i = 0; i < (int)parameters.size(); i++)
{
User *u = ServerInstance->FindNick(parameters[i]);
User *u = ServerInstance->FindNickOnly(parameters[i]);
if ((u) && (u->registered == REG_ALL))
{
// Anyone may query their own IP

View File

@ -262,35 +262,41 @@ bool irc::sockets::sockaddrs::operator==(const irc::sockets::sockaddrs& other) c
static void sa2cidr(irc::sockets::cidr_mask& cidr, const irc::sockets::sockaddrs& sa, int range)
{
const unsigned char* base;
unsigned char target_byte;
cidr.type = sa.sa.sa_family;
memset(cidr.bits, 0, sizeof(cidr.bits));
if (cidr.type == AF_INET)
{
target_byte = sizeof(sa.in4.sin_addr);
base = (unsigned char*)&sa.in4.sin_addr;
if (range > 32)
range = 32;
}
else if (cidr.type == AF_INET6)
{
target_byte = sizeof(sa.in6.sin6_addr);
base = (unsigned char*)&sa.in6.sin6_addr;
if (range > 128)
range = 128;
}
else
{
base = (unsigned char*)"";
range = 0;
cidr.length = 0;
return;
}
cidr.length = range;
unsigned int border = range / 8;
unsigned int bitmask = (0xFF00 >> (range & 7)) & 0xFF;
for(unsigned int i=0; i < 16; i++)
for(unsigned int i=0; i < target_byte; i++)
{
if (i < border)
cidr.bits[i] = base[i];
else if (i == border)
cidr.bits[i] = base[i] & bitmask;
else
cidr.bits[i] = 0;
return;
}
}

View File

@ -761,7 +761,7 @@ const std::string& User::GetIPString()
irc::sockets::satoap(client_sa, cachedip, port);
/* IP addresses starting with a : on irc are a Bad Thing (tm) */
if (cachedip[0] == ':')
cachedip.insert(0,1,'0');
cachedip.insert(cachedip.begin(),1,'0');
}
return cachedip;