1
0
mirror of https://github.com/anope/anope.git synced 2026-06-12 22:34:46 +02:00

Compare commits

...

67 Commits

Author SHA1 Message Date
Adam c2e09fdaea Anope 2.0.4 Release 2016-07-23 16:26:14 -04:00
Adam 01768bc73e Update Changes.conf 2016-07-23 16:25:37 -04:00
Adam c18eedec18 ns_set: clear last modes before unserializing them 2016-07-23 16:20:54 -04:00
Adam 0e0615c6fe Note Windows installer fixes in changelog 2016-07-23 16:17:33 -04:00
Adam 5bd3fde79b cs_set: clear last modes before unserializing them 2016-07-23 16:17:21 -04:00
Adam 647f8cd4e6 Add/fix various checks on source user existing in the protocol modules 2016-07-23 15:47:33 -04:00
Adam b2e25db159 Merge pull request #171 from Techman-/2.0+charybdis-resv-fixes
charybdis.cpp: Properly support RESVs
2016-07-23 15:38:26 -04:00
Adam 9f9371531d Fix making directories from the Windows installer 2016-07-23 15:22:54 -04:00
Michael Hazell b578ed2544 charybdis.cpp: Properly support RESVs
Properly support RESV and UNRESV in Charybdis, and improve RESV setting for pseudoclients when bursting.
2016-07-21 23:27:20 -04:00
Adam 0a7f167060 m_dns: accept unpacking the root domain, and don't consider exceptions from nameserver/additional record unpacking as fatal to query parsing 2016-07-19 21:17:58 -04:00
Adam d427772bd3 os_defcon: find module by name, it might not be loaded yet 2016-07-10 20:51:03 -04:00
Robby b2d670298b Update the dutch language file. 2016-07-07 16:07:24 +02:00
Adam 6b646fa1f8 Update Changes 2016-07-03 13:57:11 -04:00
Adam 72269c44e5 Merge pull request #170 from Zoddo/charybdis/join0
Thanks
2016-07-03 13:47:49 -04:00
Adam 3b2366e4ba Merge pull request #169 from SaberUK/2.0+which
Use "cmake --version" instead of "which cmake" to detect CMake.
2016-07-03 13:46:41 -04:00
Adam 257a8a9a24 ns_maxemail: optionally remove gmail aliases 2016-07-03 13:42:18 -04:00
Adam 7a1d2e11dd chankill: don't add duplicate akills 2016-07-03 13:31:12 -04:00
Adam 8dc687b657 #1682: store aftype with masks and include cidrs in GetNUHMask 2016-07-03 13:29:27 -04:00
Adam 18fc113984 #1681 update last realname always on signon 2016-07-03 13:06:06 -04:00
Adam 20c1a5d638 #1680: fix Anope::Duration with one year durations 2016-07-03 12:42:16 -04:00
Adam 8000ae0c0f #1677 apply sqlines even if the ircd doesn't on non opers 2016-07-03 12:36:34 -04:00
Adam 284d95bfe2 #1675: fix saset display to update the account name on the correct clients 2016-07-03 12:27:01 -04:00
Adam c7d5ee4bec Fix /ns confirm to set +r/accounts when appropriate 2016-07-03 12:17:44 -04:00
Adam 4c4cc0ded7 Fix xmlrpc notice call to return something to prevent m_xmlrpc from thinking it is a http 404 2016-07-03 12:08:21 -04:00
Adam 83f89bfece Clarify botserv repeat kicker message and allow setting repeat times to 1 2016-06-25 13:04:32 -04:00
Adam 7cf4245359 Enable -fno-delete-null-pointer-checks on GCC 6 2016-06-22 20:20:28 -04:00
Zoddo 9284441491 Handle /join 0 for ratbox & charybdis 2016-06-02 12:23:26 +02:00
Peter Powell 7592a6981b Use "cmake --version" instead of "which cmake" to detect CMake. 2016-05-21 17:54:33 +01:00
Adam 56b158ea43 Fix handling nick introduction collisions on unreal4 2016-05-20 21:18:34 -04:00
Adam 0143dafe51 Merge pull request #165 from sketchni/patch-1
Add the notice method to XMLRPC.
2016-04-22 10:17:41 -05:00
Adam a2dbcc620e Merge pull request #166 from jmdh/2.0-reproducible
Optionally strip variable build date from compiled program
2016-04-22 10:17:11 -05:00
Adam 9b5fdea8f2 Fix randomnews to work when there are more than newscount random news 2016-04-22 11:15:42 -04:00
Dominic Hargreaves fab07d6b75 Optionally strip variable build date from compiled program
To aid build reproducibility, don't include the build date/time if
-DREPRODUCIBLE_BUILD is defined.

Based on the patch provided by Alexis BienvenĂĽe in the Debian report.

Bug-Debian: https://bugs.debian.org/820152
Patch-Name: reproducible_datetime.diff
2016-04-21 23:08:12 +01:00
Sketch 1d198da436 Add the notice method to XMLRPC. 2016-04-20 15:41:23 +01:00
Adam 8b6e17fe7e Change access check in cs_updown to not allow actions on users with equal access 2016-04-16 18:14:23 -04:00
Adam 86484b6c2b Merge pull request #164 from SaberUK/2.0+extras
Remove references to cmake-bin which was removed ages ago.
2016-04-16 16:59:21 -05:00
Adam c14ae99d32 Merge pull request #163 from Zoddo/fix_sasl_reauth
Send new account name to the IRCd on SASL reauth
2016-04-16 16:59:00 -05:00
Adam cb0cda2f8d Missed channel deletion in ~ChannelInfo 2016-04-16 18:00:47 -04:00
Peter Powell 2af363755a Remove references to cmake-bin which was removed ages ago. 2016-04-16 13:05:44 +01:00
Zoddo 753b8dc989 Send new account name to the IRCd on SASL reauth 2016-04-15 10:49:30 +02:00
Adam d2ea1e7917 Merge pull request #160 from Zoddo/charybdis/fix_euid
Fix host on charybdis if there is no vhost
2016-04-14 19:18:14 -05:00
Adam a8f66578b1 Merge pull request #161 from Zoddo/charybdis/vhost_svslogin
Send vident/vhost in SVSLOGIN with SASL
2016-04-14 19:17:39 -05:00
Adam ca39aeb554 Merge pull request #162 from SaberUK/2.0+sasl
Remove support for DH-AES and DH-BLOWFISH.
2016-04-14 19:16:56 -05:00
Adam a941f9bde0 Remove memos from memoinfo more reliably 2016-04-14 20:15:53 -04:00
Peter Powell f4f6787c9c Remove support for DH-AES and DH-BLOWFISH.
These SASL mechanisms are considered insecure and should not be
used anymore.
2016-04-13 20:26:50 +01:00
Zoddo 82816cb206 Send vident/vhost in SVSLOGIN with SASL
Only charybdis seems to support that for the moment.
2016-04-10 18:24:25 +02:00
Zoddo 58f0c8c612 Fix host on charybdis if there is no vhost 2016-04-10 17:53:53 +02:00
Adam 21e1913c0f Fix subtle typo in command initializer list 2016-04-05 16:01:16 -04:00
Adam 79e7c3f98a Also defer channel deletion when processing sjoins 2016-03-19 16:21:40 -04:00
Adam 72127e1b00 Merge pull request #159 from Diftraku/2.0
proto/charybdis: Add support for MECHLIST
2016-03-17 17:15:56 -05:00
Toni Kaija ed47588087 proto/charybdis: Add support for MECHLIST 2016-03-17 15:13:11 +02:00
Adam 448967cefc Merge pull request #156 from SaberUK/2.0+sasl-mechlist
Implement support for SASL 3.2 mechanism lists.
2016-03-15 17:41:48 -05:00
Adam 979027138b Merge pull request #155 from SaberUK/2.0+sasl-reauth
Fix logging into accounts with SASL on servers that support reauth.
2016-03-15 17:40:26 -05:00
Robby 176e0e4f37 Update the dutch language file. 2016-03-09 22:42:45 +01:00
Adam b431d4dccf cs_clone: don't clone registered time 2016-03-08 19:49:30 -05:00
Adam 1b12b80b48 language: incrementing _nl_msg_cat_cntr is still required on some systems apparently (freebsd 10?). I don't know why. 2016-03-08 19:47:06 -05:00
Peter Powell 52fdc45597 Implement support for SASL 3.2 mechanism lists. 2016-02-28 16:36:43 +00:00
Peter Powell 91762524e2 Fix logging into accounts with SASL on servers that support reauth. 2016-02-28 13:22:19 +00:00
Adam 413b38b1c1 Fail sasl external auth immediately if cert is empty 2016-02-13 18:25:04 -05:00
Adam ecdccd6ad6 And use account here, user might be null 2016-02-13 18:19:47 -05:00
Adam e0fd118b3e Fix access path changes in ns_alist from earlier 2016-02-13 18:11:03 -05:00
Adam c10d7bdada Update chanserv secure help to reflect more accurately what it does 2016-02-13 14:41:23 -05:00
Adam 4e2ca31cf5 Rewrite access path system to be simplier and use recursion
Show where access is "from" in chanserv/status
2016-02-13 14:16:29 -05:00
Adam addd2a1987 Correct umode +I change in Changelog, is for unreal 2016-02-11 08:36:12 -05:00
Adam 4071487f80 Merge pull request #154 from SaberUK/2.0+inspfix
Fix a low risk privilege escalation exploit on InspIRCd with m_autoop.
2016-02-11 07:03:55 -06:00
Peter Powell 9c17c2d818 Fix a privilege escalation exploit on InspIRCd with m_autoop. 2016-02-10 08:56:23 +00:00
Adam dd9fcca45d Anope 2.0.4-git 2016-01-30 18:50:28 -05:00
60 changed files with 851 additions and 860 deletions
+14 -6
View File
@@ -87,6 +87,9 @@ if(CMAKE_COMPILER_IS_GNUCXX)
if(GCC_VERSION LESS 4.2)
message(FATAL_ERROR "Your compiler is too old to build Anope. Upgrade to GCC 4.2 or newer!")
endif(GCC_VERSION LESS 4.2)
if(GCC_VERSION GREATER 6.0 OR GCC_VERSION EQUAL 6.0)
set(CXXFLAGS "${CXXFLAGS} -fno-delete-null-pointer-checks")
endif(GCC_VERSION GREATER 6.0 OR GCC_VERSION EQUAL 6.0)
endif(CMAKE_COMPILER_IS_GNUCXX)
# If we are using a GNU compiler (have to use CXX because it seems to fail on C), we will be able to determine it's default paths for libraries and includes
@@ -239,6 +242,11 @@ option(USE_PCH "Use precompiled headers" OFF)
# source include directory so the precompiled headers work correctly.
include_directories(${Anope_BINARY_DIR}/include ${Anope_SOURCE_DIR}/include ${Anope_BINARY_DIR}/language ${Anope_SOURCE_DIR}/modules/pseudoclients)
# Pass on REPRODUCIBLE_BUILD
if(REPRODUCIBLE_BUILD)
add_definitions(-DREPRODUCIBLE_BUILD)
endif(REPRODUCIBLE_BUILD)
# If using Windows, always add the _WIN32 define
if(WIN32)
add_definitions(-D_WIN32)
@@ -481,16 +489,16 @@ get_target_property(SERVICES_BINARY ${PROGRAM_NAME} LOCATION)
get_filename_component(SERVICES_BINARY ${SERVICES_BINARY} NAME)
# At install time, create the following additional directories
install(CODE "file(MAKE_DIRECTORY \"\$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/${DB_DIR}/backups\")")
install(CODE "file(MAKE_DIRECTORY \"\$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/${LOGS_DIR}\")")
install(CODE "file(MAKE_DIRECTORY \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${DB_DIR}/backups\")")
install(CODE "file(MAKE_DIRECTORY \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${LOGS_DIR}\")")
if(WIN32)
install(CODE "file(MAKE_DIRECTORY \"\${CMAKE_INSTALL_PREFIX}/${DB_DIR}/runtime\")")
install(CODE "file(MAKE_DIRECTORY \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${DB_DIR}/runtime\")")
endif(WIN32)
# On non-Windows platforms, if RUNGROUP is set, change the permissions of the below directories, as well as the group of the data directory
if(NOT WIN32 AND RUNGROUP)
install(CODE "execute_process(COMMAND ${CHMOD} 2775 \"\$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/\${DB_DIR}/backups\")")
install(CODE "execute_process(COMMAND ${CHMOD} 2775 \"\$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/\${LOGS_DIR}\")")
install(CODE "execute_process(COMMAND ${CHGRP} -R ${RUNGROUP} \"\$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}\")")
install(CODE "execute_process(COMMAND ${CHMOD} 2775 \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/\${DB_DIR}/backups\")")
install(CODE "execute_process(COMMAND ${CHMOD} 2775 \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/\${LOGS_DIR}\")")
install(CODE "execute_process(COMMAND ${CHGRP} -R ${RUNGROUP} \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}\")")
endif(NOT WIN32 AND RUNGROUP)
# On Windows platforms, install extra files
if(WIN32)
+1 -1
View File
@@ -166,7 +166,7 @@ done
# Check for CMake and (optionally) install it
###########################################################################
which cmake > /dev/null
cmake --version 2>&1 > /dev/null
if [ $? -ne 0 ] ; then
clear
echo "Anope requires CMake 2.4 or newer, which can be downloaded at http://cmake.org or through your system's package manager."
-18
View File
@@ -542,24 +542,6 @@ module { name = "help" }
*/
#module { name = "m_sasl" }
/*
* m_sasl_dh-aes [EXTRA]
*
* Add the DH-AES mechanism to SASL.
* Requires m_sasl to be loaded.
* Requires openssl.
*/
#module { name = "m_sasl_dh-aes" }
/*
* m_sasl_dh-blowfish [EXTRA]
*
* Add the DH-BLOWFISH mechanism to SASL.
* Requires m_sasl to be loaded.
* Requires openssl.
*/
#module { name = "m_sasl_dh-blowfish" }
/*
* m_ssl_gnutls [EXTRA]
*
+21 -2
View File
@@ -1,4 +1,23 @@
Anope Version 2.0.3-git
Anope Version 2.0.4
-------------------
Add notice rpc method to XMLRPC
Fix access check in cs_updown to not allow actions on users with equal access
Fix randomnews to work when there are more than 'newscount' random news
Fix crash from handling nick introduction collisions on unreal4
Add support for GCC6
Fix handling /join 0 on ratbox
Fix saset display to update the account of the proper user
Fix nickserv/confirm to send account and +r when appropriate
Fix chankill to not add duplicate akills
Allow nickserv/maxemail to disregard gmail style aliases when comparing emails
Fix chanserv/mode when setting listmodes with CIDR ranges
Fix reported expiry time when the time is divisible by 1 year
Clearify botserv repeat kicker help and allow setting repeat times to 1
Send vident/vhost with SASL login
Add support for SASL reauth
Fix log and database backup directories to be properly created by the installer
Anope Version 2.0.3
-------------------
Add support for UnrealIRCd 4
Fix cs_access to respect chanserv/access/list privilege
@@ -16,7 +35,7 @@ Fix crash from unloading regex modules when regex xlines exist
Fix irc2sql to store away messages
Add notice method to m_xmlrpc_main
Fix numerics on InspIRCd from being sent to user UID
Fix +I on InspIRCd to be considered oper only
Fix usermode +I on UnrealIRCd to be considered oper only
Fix crash in webcpanel when deleting your own access on a channel
Fix webcpanel allowing suspended users to login
Fix hs_off on InspIRCd to not desync active user host
+5 -1
View File
@@ -1,4 +1,8 @@
Anope Version 2.0.3-git
Anope Version 2.0.4
-------------------
Removed m_sasl_dh-aes and m_sasl_dh-blowfish
Anope Version 2.0.3
-------------------
Add operserv/chankill to default globops log
Add ns_identify:maxlogins to limit the max number of concurrent logins per account
+15
View File
@@ -113,6 +113,21 @@ class AnopeXMLRPC
{
return $this->run("channel", [$channel]);
}
/**
* Sent a notice to a user.
* Returns an array containing channel information, or an array of size one
* (just containing the name) if the channel does not exist
*
* @param $source
* @param $target
* @param $message
* @return array|null
*/
public function notice($source, $target, $message)
{
return $this->run("notice", [$source, $target, $message]);
}
/**
* Like channel(), but different.
+1 -6
View File
@@ -148,12 +148,7 @@ while (1)
if ($input eq "q") {
if (-e "build/CMakeFiles") {
if (-e "cmake-bin") {
my $cmake_path = `find cmake-bin -name cmake -print0`;
system($cmake_path, "build/.");
} else {
system("cmake", "build/.");
}
system("cmake", "build/.");
print "\nNow cd build, then run make to build Anope.\n\n";
} else {
print "\nBuild directory not found. You should run ./Config now.\n\n"
+10 -11
View File
@@ -78,12 +78,7 @@ class CoreExport ChanAccess : public Serializable
Serialize::Reference<NickCore> nc;
public:
typedef std::multimap<const ChanAccess *, const ChanAccess *> Set;
/* shows the 'path' taken to determine if an access entry matches a user
* .first are access entries checked
* .second are access entries which match
*/
typedef std::pair<Set, Set> Path;
typedef std::vector<ChanAccess *> Path;
/* The provider that created this access entry */
AccessProvider *provider;
@@ -103,12 +98,14 @@ class CoreExport ChanAccess : public Serializable
void Serialize(Serialize::Data &data) const anope_override;
static Serializable* Unserialize(Serializable *obj, Serialize::Data &);
static const unsigned int MAX_DEPTH = 4;
/** Check if this access entry matches the given user or account
* @param u The user
* @param nc The account
* @param p The path to the access object which matches will be put here
* @param next Next channel to check if any
*/
virtual bool Matches(const User *u, const NickCore *nc, Path &p) const;
virtual bool Matches(const User *u, const NickCore *nc, ChannelInfo* &next) const;
/** Check if this access entry has the given privilege.
* @param name The privilege name
@@ -136,13 +133,13 @@ class CoreExport ChanAccess : public Serializable
/* A group of access entries. This is used commonly, for example with ChannelInfo::AccessFor,
* to show what access a user has on a channel because users can match multiple access entries.
*/
class CoreExport AccessGroup : public std::vector<ChanAccess *>
class CoreExport AccessGroup
{
public:
/* access entries + paths */
std::vector<ChanAccess::Path> paths;
/* Channel these access entries are on */
const ChannelInfo *ci;
/* Path from these entries to other entries that they depend on */
ChanAccess::Path path;
/* Account these entries affect, if any */
const NickCore *nc;
/* super_admin always gets all privs. founder is a special case where ci->founder == nc */
@@ -170,6 +167,8 @@ class CoreExport AccessGroup : public std::vector<ChanAccess *>
bool operator<(const AccessGroup &other) const;
bool operator>=(const AccessGroup &other) const;
bool operator<=(const AccessGroup &other) const;
inline bool empty() const { return paths.empty(); }
};
#endif
+2
View File
@@ -336,7 +336,9 @@ namespace Anope
template<typename T> class multimap : public std::multimap<string, T, ci::less> { };
template<typename T> class hash_map : public TR1NS::unordered_map<string, T, hash_ci, compare> { };
#ifndef REPRODUCIBLE_BUILD
static const char *const compiled = __TIME__ " " __DATE__;
#endif
/** The time Anope started.
*/
+2
View File
@@ -302,6 +302,8 @@ class CoreExport Channel : public Base, public Extensible
*/
static Channel *FindOrCreate(const Anope::string &name, bool &created, time_t ts = Anope::CurTime);
void QueueForDeletion();
static void DeleteChannels();
};
+1
View File
@@ -18,6 +18,7 @@
class CoreExport Memo : public Serializable
{
public:
MemoInfo *mi;
bool unread;
bool receipt;
Memo();
+1
View File
@@ -395,6 +395,7 @@ class CoreExport Entry
Anope::string mask;
public:
unsigned short cidr_len;
int family;
Anope::string nick, user, host, real;
/** Constructor
+2 -1
View File
@@ -227,8 +227,9 @@ class CoreExport IRCDProto : public Service
*/
virtual void SendOper(User *u);
virtual void SendSASLMechanisms(std::vector<Anope::string> &) { }
virtual void SendSASLMessage(const SASL::Message &) { }
virtual void SendSVSLogin(const Anope::string &uid, const Anope::string &acc) { }
virtual void SendSVSLogin(const Anope::string &uid, const Anope::string &acc, const Anope::string &vident, const Anope::string &vhost) { }
virtual bool IsNickValid(const Anope::string &);
virtual bool IsChannelValid(const Anope::string &);
+4
View File
@@ -38,6 +38,10 @@ union CoreExport sockaddrs
*/
void clear();
/** Get address family.
*/
int family() const;
/** Get the size of the sockaddr we represent
* @return The size
*/
+273 -248
View File
File diff suppressed because it is too large Load Diff
+19 -6
View File
@@ -663,17 +663,30 @@ class CommandBSKickRepeat : public CommandBSKickBase
kd->repeattimes = convertTo<int16_t>(times);
}
catch (const ConvertException &) { }
if (kd->repeattimes < 2)
if (kd->repeattimes < 1)
kd->repeattimes = 3;
kd->repeat = true;
if (kd->ttb[TTB_REPEAT])
source.Reply(_("Bot will now kick for \002repeats\002 (users that say the\n"
"same thing %d times), and will place a ban after %d\n"
"kicks for the same user."), kd->repeattimes + 1, kd->ttb[TTB_REPEAT]);
{
if (kd->repeattimes != 1)
source.Reply(_("Bot will now kick for \002repeats\002 (users that repeat the\n"
"same message %d times), and will place a ban after %d\n"
"kicks for the same user."), kd->repeattimes, kd->ttb[TTB_REPEAT]);
else
source.Reply(_("Bot will now kick for \002repeats\002 (users that repeat the\n"
"same message %d time), and will place a ban after %d\n"
"kicks for the same user."), kd->repeattimes, kd->ttb[TTB_REPEAT]);
}
else
source.Reply(_("Bot will now kick for \002repeats\002 (users that say the\n"
"same thing %d times)."), kd->repeattimes + 1);
{
if (kd->repeattimes != 1)
source.Reply(_("Bot will now kick for \002repeats\002 (users that repeat the\n"
"same message %d times)."), kd->repeattimes);
else
source.Reply(_("Bot will now kick for \002repeats\002 (users that repeat the\n"
"same message %d time)."), kd->repeattimes);
}
}
else if (params[1].equals_ci("OFF"))
{
+2 -2
View File
@@ -370,7 +370,7 @@ class CommandCSAccess : public Command
if (ci->c)
for (Channel::ChanUserList::const_iterator cit = ci->c->users.begin(), cit_end = ci->c->users.end(); cit != cit_end; ++cit)
{
ChanAccess::Path p;
ChannelInfo *p;
if (access->Matches(cit->second->user, cit->second->user->Account(), p))
timebuf = "Now";
}
@@ -407,7 +407,7 @@ class CommandCSAccess : public Command
if (ci->c)
for (Channel::ChanUserList::const_iterator cit = ci->c->users.begin(), cit_end = ci->c->users.end(); cit != cit_end; ++cit)
{
ChanAccess::Path p;
ChannelInfo *p;
if (access->Matches(cit->second->user, cit->second->user->Account(), p))
timebuf = "Now";
}
+1
View File
@@ -169,6 +169,7 @@ public:
delete target_ci;
target_ci = new ChannelInfo(*ci);
target_ci->name = target;
target_ci->time_registered = Anope::CurTime;
(*RegisteredChannelList)[target_ci->name] = target_ci;
target_ci->c = Channel::Find(target_ci->name);
+7 -2
View File
@@ -236,9 +236,14 @@ class CommandSeen : public Command
AccessGroup ag = source.c->ci->AccessFor(na->nc);
time_t last = 0;
for (unsigned i = 0; i < ag.size(); ++i)
for (unsigned int i = 0; i < ag.paths.size(); ++i)
{
ChanAccess *a = ag[i];
ChanAccess::Path &p = ag.paths[i];
if (p.empty())
continue;
ChanAccess *a = p[p.size() - 1];
if (a->GetAccount() == na->nc && a->last_seen > last)
last = a->last_seen;
+4 -4
View File
@@ -742,10 +742,9 @@ class CommandCSSetSecure : public Command
this->SendSyntax(source);
source.Reply(" ");
source.Reply(_("Enables or disables security features for a\n"
"channel. When \002%s\002 is set, only users who have\n"
"registered their nicknames and IDENTIFY'd\n"
"with their password will be given access to the channel\n"
"as controlled by the access list."), this->name.c_str());
"channel. When \002SECURE\002 is set, only users who have\n"
"identified to services, and are not only recognized, will be\n"
"given access to channels from account-based access entries."));
return true;
}
};
@@ -1136,6 +1135,7 @@ class CSSet : public Module
ChannelInfo *ci = anope_dynamic_static_cast<ChannelInfo *>(s);
Anope::string modes;
data["last_modes"] >> modes;
ci->last_modes.clear();
for (spacesepstream sep(modes); sep.GetToken(modes);)
{
size_t c = modes.find(',');
+18 -3
View File
@@ -57,11 +57,26 @@ public:
{
source.Reply(_("Access for \002%s\002 on \002%s\002:"), nick.c_str(), ci->name.c_str());
for (unsigned i = 0; i < ag.size(); ++i)
for (unsigned i = 0; i < ag.paths.size(); ++i)
{
ChanAccess *acc = ag[i];
ChanAccess::Path &p = ag.paths[i];
source.Reply(_("\002%s\002 matches access entry %s, which has privilege %s."), nick.c_str(), acc->Mask().c_str(), acc->AccessSerialize().c_str());
if (p.empty())
continue;
if (p.size() == 1)
{
ChanAccess *acc = p[0];
source.Reply(_("\002%s\002 matches access entry %s, which has privilege %s."), nick.c_str(), acc->Mask().c_str(), acc->AccessSerialize().c_str());
}
else
{
ChanAccess *first = p[0];
ChanAccess *acc = p[p.size() - 1];
source.Reply(_("\002%s\002 matches access entry %s (from entry %s), which has privilege %s."), nick.c_str(), acc->Mask().c_str(), first->Mask().c_str(), acc->AccessSerialize().c_str());
}
}
}
+2 -2
View File
@@ -101,7 +101,7 @@ class CommandCSUp : public Command
}
else if (source.GetUser() && u != source.GetUser() && c->ci->HasExt("PEACE"))
{
if (c->ci->AccessFor(u) > c->ci->AccessFor(source.GetUser()))
if (c->ci->AccessFor(u) >= c->ci->AccessFor(source.GetUser()))
{
if (source.HasPriv("chanserv/administration"))
override = true;
@@ -199,7 +199,7 @@ class CommandCSDown : public Command
}
else if (source.GetUser() && u != source.GetUser() && c->ci->HasExt("PEACE"))
{
if (c->ci->AccessFor(u) > c->ci->AccessFor(source.GetUser()))
if (c->ci->AccessFor(u) >= c->ci->AccessFor(source.GetUser()))
{
if (source.HasPriv("chanserv/administration"))
override = true;
+11 -2
View File
@@ -86,8 +86,17 @@ class CommandNSAList : public Command
entry["Number"] = stringify(chan_count);
entry["Channel"] = (ci->HasExt("CS_NO_EXPIRE") ? "!" : "") + ci->name;
for (unsigned j = 0; j < access.size(); ++j)
entry["Access"] = entry["Access"] + ", " + access[j]->AccessSerialize();
for (unsigned j = 0; j < access.paths.size(); ++j)
{
ChanAccess::Path &p = access.paths[j];
// not interested in indirect access
if (p.size() != 1)
continue;
ChanAccess *a = p[0];
entry["Access"] = entry["Access"] + ", " + a->AccessSerialize();
}
entry["Access"] = entry["Access"].substr(2);
entry["Description"] = ci->desc;
list.AddEntry(entry);
+14
View File
@@ -40,6 +40,20 @@ class CommandNSConfirm : public Command
FOREACH_MOD(OnNickConfirm, (source.GetUser(), na->nc));
Log(LOG_ADMIN, source, this) << "to confirm nick " << na->nick << " (" << na->nc->display << ")";
source.Reply(_("Nick \002%s\002 has been confirmed."), na->nick.c_str());
/* Login the users online already */
for (std::list<User *>::iterator it = na->nc->users.begin(); it != na->nc->users.end(); ++it)
{
User *u = *it;
IRCD->SendLogin(u, na);
NickAlias *u_na = NickAlias::Find(u->nick);
/* Set +r if they're on a nick in the group */
if (!Config->GetModule("nickserv")->Get<bool>("nonicknameownership") && u_na && *u_na->nc == *na->nc)
u->SetMode(source.service, "REGISTERED");
}
}
}
else if (source.nc)
+9 -2
View File
@@ -361,8 +361,14 @@ class CommandNSSetDisplay : public Command
Log(user_na->nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to change the display of " << user_na->nc->display << " to " << na->nick;
user_na->nc->SetDisplay(na);
if (source.GetUser())
IRCD->SendLogin(source.GetUser(), na);
/* Send updated account name */
for (std::list<User *>::iterator it = user_na->nc->users.begin(); it != user_na->nc->users.end(); ++it)
{
User *u = *it;
IRCD->SendLogin(u, user_na);
}
source.Reply(NICK_SET_DISPLAY_CHANGED, user_na->nc->display.c_str());
}
@@ -1205,6 +1211,7 @@ class NSSet : public Module
NickCore *nc = anope_dynamic_static_cast<NickCore *>(s);
Anope::string modes;
data["last_modes"] >> modes;
nc->last_modes.clear();
for (spacesepstream sep(modes); sep.GetToken(modes);)
{
size_t c = modes.find(',');
+5 -1
View File
@@ -76,7 +76,11 @@ class CommandOSChanKill : public Command
if (uc->user->server == Me || uc->user->HasMode("OPER"))
continue;
XLine *x = new XLine("*@" + uc->user->host, source.GetNick(), expires, realreason, XLineManager::GenerateUID());
Anope::string akillmask = "*@" + uc->user->host;
if (akills->HasEntry(akillmask))
continue;
XLine *x = new XLine(akillmask, source.GetNick(), expires, realreason, XLineManager::GenerateUID());
akills->AddXLine(x);
akills->OnMatch(uc->user, x);
}
+1 -2
View File
@@ -354,8 +354,7 @@ class OSDefcon : public Module
dconfig.message = block->Get<const Anope::string>("message");
dconfig.offmessage = block->Get<const Anope::string>("offmessage");
Module *session = ModuleManager::FindModule("os_session");
block = conf->GetModule(session);
block = conf->GetModule("os_session");
dconfig.max_session_kill = block->Get<int>("maxsessionkill");
dconfig.session_autokill_expiry = block->Get<time_t>("sessionautokillexpiry");
+1 -1
View File
@@ -405,7 +405,7 @@ class OSNews : public Module
int start = 0;
if (type != NEWS_RANDOM)
if (Type != NEWS_RANDOM)
{
start = newsList.size() - news_count;
if (start < 0)
+4 -4
View File
@@ -23,8 +23,8 @@ class StatusUpdate : public Module
{
User *user = it->second->user;
ChanAccess::Path p;
if (user->server != Me && access->Matches(user, user->Account(), p))
ChannelInfo *next;
if (user->server != Me && access->Matches(user, user->Account(), next))
{
AccessGroup ag = ci->AccessFor(user);
@@ -46,8 +46,8 @@ class StatusUpdate : public Module
{
User *user = it->second->user;
ChanAccess::Path p;
if (user->server != Me && access->Matches(user, user->Account(), p))
ChannelInfo *next;
if (user->server != Me && access->Matches(user, user->Account(), next))
{
AccessGroup ag = ci->AccessFor(user);
+2
View File
@@ -590,6 +590,7 @@ static void LoadNicks()
READ(read_string(m->text, f));
m->owner = nc->display;
nc->memos.memos->push_back(m);
m->mi = &nc->memos;
}
READ(read_uint16(&u16, f));
READ(read_int16(&i16, f));
@@ -956,6 +957,7 @@ static void LoadChannels()
READ(read_string(m->text, f));
m->owner = ci->name;
ci->memos.memos->push_back(m);
m->mi = &ci->memos;
}
READ(read_string(buffer, f));
-193
View File
@@ -1,193 +0,0 @@
/*
*
* (C) 2014 Daniel Vassdal <shutter@canternet.org>
* (C) 2014-2016 Anope Team
* Contact us at team@anope.org
*
* Please read COPYING and README for further details.
*/
/* RequiredLibraries: ssl,crypto */
/* RequiredWindowsLibraries: ssleay32,libeay32 */
#include "module.h"
#include "modules/sasl.h"
#include <openssl/bn.h>
#include <openssl/dh.h>
#include <openssl/aes.h>
using namespace SASL;
class DHAES : public Mechanism
{
void Err(Session* sess, BIGNUM* key = NULL)
{
if (key)
BN_free(key);
sasl->Fail(sess);
delete sess;
}
public:
struct DHAESSession : SASL::Session
{
DH* dh;
DHAESSession(Mechanism *m, const Anope::string &u, DH* dh_params) : SASL::Session(m, u)
{
if (!(dh = DH_new()))
return;
dh->g = BN_dup(dh_params->g);
dh->p = BN_dup(dh_params->p);
if (!DH_generate_key(dh))
{
DH_free(dh);
dh = NULL;
}
}
~DHAESSession()
{
if (dh)
DH_free(dh);
}
};
DH* dh_params;
const size_t keysize;
SASL::Session* CreateSession(const Anope::string &uid) anope_override
{
return new DHAESSession(this, uid, dh_params);
}
DHAES(Module *o) : Mechanism(o, "DH-AES"), keysize(256 / 8)
{
if (!(dh_params = DH_new()))
throw ModuleException("DH_new() failed!");
if (!DH_generate_parameters_ex(dh_params, keysize * 8, 5, NULL))
{
DH_free(dh_params);
throw ModuleException("Could not generate DH-params");
}
}
~DHAES()
{
DH_free(dh_params);
}
void ProcessMessage(SASL::Session *session, const SASL::Message &m) anope_override
{
DHAESSession *sess = anope_dynamic_static_cast<DHAESSession *>(session);
if (!sess->dh)
{
sasl->SendMessage(sess, "D", "A");
delete sess;
return;
}
if (m.type == "S")
{
// Format: [ss]<p>[ss]<g>[ss]<pub_key>
// Where ss is a unsigned short with the size of the key
const BIGNUM* dhval[] = { sess->dh->p, sess->dh->g, sess->dh->pub_key };
// Find the size of our buffer - initialized at 6 because of string size data
size_t size = 6;
for (size_t i = 0; i < 3; i++)
size += BN_num_bytes(dhval[i]);
// Fill in the DH data
std::vector<unsigned char> buffer(size);
for (size_t i = 0, pos = 0; i < 3; i++)
{
*reinterpret_cast<uint16_t*>(&buffer[pos]) = htons(BN_num_bytes(dhval[i]));
pos += 2;
BN_bn2bin(dhval[i], &buffer[pos]);
pos += BN_num_bytes(dhval[i]);
}
Anope::string encoded;
Anope::B64Encode(Anope::string(buffer.begin(), buffer.end()), encoded);
sasl->SendMessage(sess, "C", encoded);
}
else if (m.type == "C")
{
// Make sure we have some data - actual size check is done later
if (m.data.length() < 10)
return Err(sess);
// Format: [ss]<key>[ss]<iv>[ss]<encrypted>
// <encrypted> = <username>\0<password>\0
Anope::string decoded;
Anope::B64Decode(m.data, decoded);
// Make sure we have an IV and at least one encrypted block
if ((decoded.length() < keysize + 2 + (AES_BLOCK_SIZE * 2)) || ((decoded.length() - keysize - 2) % AES_BLOCK_SIZE))
return Err(sess);
const unsigned char* data = reinterpret_cast<const unsigned char*>(decoded.data());
// Control the size of the key
if (ntohs(*reinterpret_cast<const uint16_t*>(&data[0])) != keysize)
return Err(sess);
// Convert pubkey from binary
size_t pos = 2;
BIGNUM* pubkey = BN_bin2bn(&data[pos], keysize, NULL);
if (!pubkey)
return Err(sess);
// Find shared key
std::vector<unsigned char> secretkey(keysize);
if (DH_compute_key(&secretkey[0], pubkey, sess->dh) != static_cast<int>(keysize))
return Err(sess, pubkey);
// Set decryption key
AES_KEY AESKey;
AES_set_decrypt_key(&secretkey[0], keysize * 8, &AESKey);
// Fetch IV
pos += keysize;
std::vector<unsigned char> IV(data + pos, data + pos + AES_BLOCK_SIZE);
// Find encrypted blocks, and decrypt
pos += AES_BLOCK_SIZE;
size_t size = decoded.length() - pos;
std::vector<char> decrypted(size + 2, 0);
AES_cbc_encrypt(&data[pos], reinterpret_cast<unsigned char*>(&decrypted[0]), size, &AESKey, &IV[0], AES_DECRYPT);
std::string username = &decrypted[0];
std::string password = &decrypted[username.length() + 1];
if (username.empty() || password.empty() || !IRCD->IsNickValid(username) || password.find_first_of("\r\n") != Anope::string::npos)
return Err(sess, pubkey);
SASL::IdentifyRequest* req = new SASL::IdentifyRequest(this->owner, m.source, username, password);
FOREACH_MOD(OnCheckAuthentication, (NULL, req));
req->Dispatch();
BN_free(pubkey);
}
}
};
class ModuleSASLDHAES : public Module
{
DHAES dhaes;
public:
ModuleSASLDHAES(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR | EXTRA),
dhaes(this)
{
}
};
MODULE_INIT(ModuleSASLDHAES)
-203
View File
@@ -1,203 +0,0 @@
/*
*
* (C) 2014 Daniel Vassdal <shutter@canternet.org>
* (C) 2011-2016 Anope Team
* Contact us at team@anope.org
*
* Please read COPYING and README for further details.
*/
/* RequiredLibraries: ssl,crypto */
/* RequiredWindowsLibraries: ssleay32,libeay32 */
#include "module.h"
#include "modules/sasl.h"
#include <openssl/bn.h>
#include <openssl/dh.h>
#include <openssl/blowfish.h>
using namespace SASL;
class DHBS : public Mechanism
{
void Err(Session* sess, BIGNUM* key = NULL)
{
if (key)
BN_free(key);
sasl->Fail(sess);
delete sess;
}
public:
struct DHBSSession : SASL::Session
{
DH* dh;
DHBSSession(Mechanism *m, const Anope::string &u, DH* dh_params) : SASL::Session(m, u)
{
if (!(dh = DH_new()))
return;
dh->g = BN_dup(dh_params->g);
dh->p = BN_dup(dh_params->p);
if (!DH_generate_key(dh))
{
DH_free(dh);
dh = NULL;
}
}
~DHBSSession()
{
if (dh)
DH_free(dh);
}
};
DH* dh_params;
const size_t keysize;
SASL::Session* CreateSession(const Anope::string &uid) anope_override
{
return new DHBSSession(this, uid, dh_params);
}
DHBS(Module *o) : Mechanism(o, "DH-BLOWFISH"), keysize(256 / 8)
{
if (!(dh_params = DH_new()))
throw ModuleException("DH_new() failed!");
if (!DH_generate_parameters_ex(dh_params, keysize * 8, 5, NULL))
{
DH_free(dh_params);
throw ModuleException("Could not generate DH-params");
}
}
~DHBS()
{
DH_free(dh_params);
}
void ProcessMessage(SASL::Session *session, const SASL::Message &m) anope_override
{
DHBSSession *sess = anope_dynamic_static_cast<DHBSSession *>(session);
if (!sess->dh)
{
sasl->SendMessage(sess, "D", "A");
delete sess;
return;
}
if (m.type == "S")
{
// Format: [ss]<p>[ss]<g>[ss]<pub_key>
// Where ss is a unsigned short with the size of the key
const BIGNUM* dhval[] = { sess->dh->p, sess->dh->g, sess->dh->pub_key };
// Find the size of our buffer - initialized at 6 because of string size data
size_t size = 6;
for (size_t i = 0; i < 3; i++)
size += BN_num_bytes(dhval[i]);
// Fill in the DH data
std::vector<unsigned char> buffer(size);
for (size_t i = 0, pos = 0; i < 3; i++)
{
*reinterpret_cast<uint16_t*>(&buffer[pos]) = htons(BN_num_bytes(dhval[i]));
pos += 2;
BN_bn2bin(dhval[i], &buffer[pos]);
pos += BN_num_bytes(dhval[i]);
}
Anope::string encoded;
Anope::B64Encode(Anope::string(buffer.begin(), buffer.end()), encoded);
sasl->SendMessage(sess, "C", encoded);
}
else if (m.type == "C")
{
// Make sure we have some data - actual size check is done later
if (m.data.length() < 10)
return Err(sess);
// Format: [ss]<key><username><\0><encrypted>
Anope::string decoded;
Anope::B64Decode(m.data, decoded);
// As we rely on the client giving us a null terminator at the right place,
// let's add one extra in case the client tries to crash us
const size_t decodedlen = decoded.length();
decoded.push_back('\0');
// Make sure we have enough data for at least the key, a one letter username, and a block of data
if (decodedlen < keysize + 2 + 2 + 8)
return Err(sess);
const unsigned char* data = reinterpret_cast<const unsigned char*>(decoded.data());
// Control the size of the key
if (ntohs(*reinterpret_cast<const uint16_t*>(&data[0])) != keysize)
return Err(sess);
// Convert pubkey from binary
size_t pos = 2;
BIGNUM* pubkey = BN_bin2bn(&data[pos], keysize, NULL);
if (!pubkey)
return Err(sess);
// Find shared key
std::vector<unsigned char> secretkey(DH_size(sess->dh) + 1, 0);
if (DH_compute_key(&secretkey[0], pubkey, sess->dh) != static_cast<int>(keysize))
return Err(sess, pubkey);
// Set decryption key
BF_KEY BFKey;
BF_set_key(&BFKey, keysize, &secretkey[0]);
pos += keysize;
const Anope::string username = reinterpret_cast<const char*>(&data[pos]);
// Check that the username is valid, and that we have at least one block of data
// 2 + 1 + 8 = uint16_t size for keylen, \0 for username, 8 for one block of data
if (username.empty() || username.length() + keysize + 2 + 1 + 8 > decodedlen || !IRCD->IsNickValid(username))
return Err(sess, pubkey);
pos += username.length() + 1;
size_t size = decodedlen - pos;
// Blowfish data blocks are 64 bits wide - valid format?
if (size % 8)
return Err(sess, pubkey);
std::vector<char> decrypted(size + 1, 0);
for (size_t i = 0; i < size; i += 8)
BF_ecb_encrypt(&data[pos + i], reinterpret_cast<unsigned char*>(&decrypted[i]), &BFKey, BF_DECRYPT);
std::string password = &decrypted[0];
if (password.empty() || password.find_first_of("\r\n") != Anope::string::npos)
return Err(sess, pubkey);
SASL::IdentifyRequest* req = new SASL::IdentifyRequest(this->owner, m.source, username, password);
FOREACH_MOD(OnCheckAuthentication, (NULL, req));
req->Dispatch();
BN_free(pubkey);
}
}
};
class ModuleSASLDHBS : public Module
{
DHBS dhbs;
public:
ModuleSASLDHBS(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR | EXTRA),
dhbs(this)
{
}
};
MODULE_INIT(ModuleSASLDHBS)
+12 -6
View File
@@ -103,8 +103,7 @@ class Packet : public Query
/* +1 pos either to one byte after the compression pointer or one byte after the ending \0 */
++pos;
if (name.empty())
throw SocketException("Unable to unpack name - no name");
/* Empty names are valid (root domain) */
Log(LOG_DEBUG_2) << "Resolver: UnpackName successfully unpacked " << name;
@@ -253,11 +252,18 @@ class Packet : public Query
for (unsigned i = 0; i < ancount; ++i)
this->answers.push_back(this->UnpackResourceRecord(input, len, packet_pos));
for (unsigned i = 0; i < nscount; ++i)
this->authorities.push_back(this->UnpackResourceRecord(input, len, packet_pos));
try
{
for (unsigned i = 0; i < nscount; ++i)
this->authorities.push_back(this->UnpackResourceRecord(input, len, packet_pos));
for (unsigned i = 0; i < arcount; ++i)
this->additional.push_back(this->UnpackResourceRecord(input, len, packet_pos));
for (unsigned i = 0; i < arcount; ++i)
this->additional.push_back(this->UnpackResourceRecord(input, len, packet_pos));
}
catch (const SocketException &ex)
{
Log(LOG_DEBUG_2) << "Unable to parse ns/ar records: " << ex.GetReason();
}
}
unsigned short Pack(unsigned char *output, unsigned short output_size)
+45 -2
View File
@@ -97,7 +97,7 @@ class External : public Mechanism
}
else if (m.type == "C")
{
if (!certs)
if (!certs || mysess->cert.empty())
{
sasl->Fail(sess);
delete sess;
@@ -223,7 +223,18 @@ class SASLService : public SASL::Service, public Timer
void Succeed(Session *session, NickCore *nc) anope_override
{
IRCD->SendSVSLogin(session->uid, nc->display);
// If the user is already introduced then we log them in now.
// Otherwise, we send an SVSLOGIN to log them in later.
User *user = User::Find(session->uid);
NickAlias *na = NickAlias::Find(nc->display);
if (user)
{
user->Identify(na);
}
else
{
IRCD->SendSVSLogin(session->uid, nc->display, na->GetVhostIdent(), na->GetVhostHost());
}
this->SendMessage(session, "D", "S");
}
@@ -266,6 +277,21 @@ class ModuleSASL : public Module
Plain plain;
External *external;
std::vector<Anope::string> mechs;
void CheckMechs()
{
std::vector<Anope::string> newmechs = ::Service::GetServiceKeys("SASL::Mechanism");
if (newmechs == mechs)
return;
mechs = newmechs;
// If we are connected to the network then broadcast the mechlist.
if (Me && Me->IsSynced())
IRCD->SendSASLMechanisms(mechs);
}
public:
ModuleSASL(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
sasl(this), plain(this), external(NULL)
@@ -273,6 +299,7 @@ class ModuleSASL : public Module
try
{
external = new External(this);
CheckMechs();
}
catch (ModuleException &) { }
}
@@ -281,6 +308,22 @@ class ModuleSASL : public Module
{
delete external;
}
void OnModuleLoad(User *, Module *) anope_override
{
CheckMechs();
}
void OnModuleUnload(User *, Module *) anope_override
{
CheckMechs();
}
void OnPreUplinkSync(Server *) anope_override
{
// We have not yet sent a mechanism list so always do it here.
IRCD->SendSASLMechanisms(mechs);
}
};
MODULE_INIT(ModuleSASL)
+2
View File
@@ -273,6 +273,8 @@ class MyXMLRPCEvent : public XMLRPCEvent
return;
u->SendMessage(bi, message);
request.reply("result", "Success");
}
};
+32 -1
View File
@@ -14,6 +14,27 @@
class NSMaxEmail : public Module
{
bool clean;
/* strip dots from username, and remove anything after the first + */
Anope::string CleanMail(const Anope::string &email)
{
size_t host = email.find('@');
if (host == Anope::string::npos)
return email;
Anope::string username = email.substr(0, host);
username = username.replace_all_cs(".", "");
size_t sz = username.find('+');
if (sz != Anope::string::npos)
username = username.substr(0, sz);
Anope::string cleaned = username + email.substr(host);
Log(LOG_DEBUG) << "cleaned " << email << " to " << cleaned;
return cleaned;
}
bool CheckLimitReached(CommandSource &source, const Anope::string &email)
{
int NSEmailMax = Config->GetModule(this)->Get<int>("maxemails");
@@ -39,11 +60,15 @@ class NSMaxEmail : public Module
if (email.empty())
return 0;
Anope::string cleanemail = clean ? CleanMail(email) : email;
for (nickcore_map::const_iterator it = NickCoreList->begin(), it_end = NickCoreList->end(); it != it_end; ++it)
{
const NickCore *nc = it->second;
if (unc != nc && !nc->email.empty() && nc->email.equals_ci(email))
Anope::string cleannc = clean ? CleanMail(nc->email) : nc->email;
if (unc != nc && cleanemail == cleannc)
++count;
}
@@ -52,9 +77,15 @@ class NSMaxEmail : public Module
public:
NSMaxEmail(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR)
, clean(false)
{
}
void OnReload(Configuration::Conf *conf) anope_override
{
clean = conf->GetModule(this)->Get<bool>("remove_aliases", "true");
}
EventReturn OnPreCommand(CommandSource &source, Command *command, std::vector<Anope::string> &params) anope_override
{
if (source.IsOper())
+6 -1
View File
@@ -386,7 +386,12 @@ struct IRCDMessageNick : IRCDMessage
User::OnIntroduce(params[0], params[4], params[5], "", params[8], s, params[9], signon, params[3], "", na ? *na->nc : NULL);
}
else
source.GetUser()->ChangeNick(params[0]);
{
User *u = source.GetUser();
if (u)
u->ChangeNick(params[0]);
}
}
};
+48 -6
View File
@@ -31,13 +31,29 @@ class ChannelModeLargeBan : public ChannelMode
class CharybdisProto : public IRCDProto
{
BotInfo *FindIntroduced()
{
BotInfo *bi = Config->GetClient("OperServ");
if (bi && bi->introduced)
return bi;
for (botinfo_map::iterator it = BotListByNick->begin(), it_end = BotListByNick->end(); it != it_end; ++it)
if (it->second->introduced)
return it->second;
return NULL;
}
public:
CharybdisProto(Module *creator) : IRCDProto(creator, "Charybdis 3.4+")
{
DefaultPseudoclientModes = "+oiS";
CanCertFP = true;
CanSNLine = true;
CanSQLine = true;
CanSQLineChannel = true;
CanSZLine = true;
CanSVSNick = true;
CanSVSHold = true;
@@ -54,7 +70,6 @@ class CharybdisProto : public IRCDProto
void SendSGLineDel(const XLine *x) anope_override { ratbox->SendSGLineDel(x); }
void SendAkill(User *u, XLine *x) anope_override { ratbox->SendAkill(u, x); }
void SendAkillDel(const XLine *x) anope_override { ratbox->SendAkillDel(x); }
void SendSQLineDel(const XLine *x) anope_override { ratbox->SendSQLineDel(x); }
void SendJoin(User *user, Channel *c, const ChannelStatus *status) anope_override { ratbox->SendJoin(user, c, status); }
void SendServer(const Server *server) anope_override { ratbox->SendServer(server); }
void SendChannel(Channel *c) anope_override { ratbox->SendChannel(c); }
@@ -63,9 +78,32 @@ class CharybdisProto : public IRCDProto
void SendLogin(User *u, NickAlias *na) anope_override { ratbox->SendLogin(u, na); }
void SendLogout(User *u) anope_override { ratbox->SendLogout(u); }
void SendSASLMechanisms(std::vector<Anope::string> &mechanisms) anope_override
{
Anope::string mechlist;
for (unsigned i = 0; i < mechanisms.size(); ++i)
{
mechlist += "," + mechanisms[i];
}
UplinkSocket::Message(Me) << "ENCAP * MECHLIST :" << (mechanisms.empty() ? "" : mechlist.substr(1));
}
void SendSQLine(User *, const XLine *x) anope_override
{
UplinkSocket::Message(Me) << "RESV * " << x->mask << " :" << x->GetReason();
/* Calculate the time left before this would expire, capping it at 2 days */
time_t timeleft = x->expires - Anope::CurTime;
if (timeleft > 172800 || !x->expires)
timeleft = 172800;
UplinkSocket::Message(FindIntroduced()) << "ENCAP * RESV " << timeleft << " " << x->mask << " 0 :" << x->GetReason();
}
void SendSQLineDel(const XLine *x) anope_override
{
UplinkSocket::Message(Config->GetClient("OperServ")) << "ENCAP * UNRESV " << x->mask;
}
void SendConnect() anope_override
@@ -147,17 +185,21 @@ class CharybdisProto : public IRCDProto
UplinkSocket::Message(Me) << "ENCAP " << (s ? s->GetName() : message.target.substr(0, 3)) << " SASL " << message.source << " " << message.target << " " << message.type << " " << message.data << (message.ext.empty() ? "" : (" " + message.ext));
}
void SendSVSLogin(const Anope::string &uid, const Anope::string &acc) anope_override
void SendSVSLogin(const Anope::string &uid, const Anope::string &acc, const Anope::string &vident, const Anope::string &vhost) anope_override
{
Server *s = Server::Find(uid.substr(0, 3));
UplinkSocket::Message(Me) << "ENCAP " << (s ? s->GetName() : uid.substr(0, 3)) << " SVSLOGIN " << uid << " * * * " << acc;
UplinkSocket::Message(Me) << "ENCAP " << (s ? s->GetName() : uid.substr(0, 3)) << " SVSLOGIN " << uid << " * " << (!vident.empty() ? vident : '*') << " " << (!vhost.empty() ? vhost : '*') << " " << acc;
}
};
struct IRCDMessageEncap : IRCDMessage
{
IRCDMessageEncap(Module *creator) : IRCDMessage(creator, "ENCAP", 3) { SetFlag(IRCDMESSAGE_SOFT_LIMIT);}
IRCDMessageEncap(Module *creator) : IRCDMessage(creator, "ENCAP", 3)
{
SetFlag(IRCDMESSAGE_SOFT_LIMIT);
SetFlag(IRCDMESSAGE_REQUIRE_USER);
}
void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
{
@@ -225,7 +267,7 @@ struct IRCDMessageEUID : IRCDMessage
if (params[9] != "*")
na = NickAlias::Find(params[9]);
User::OnIntroduce(params[0], params[4], params[8], params[5], params[6], source.GetServer(), params[10], params[2].is_pos_number_only() ? convertTo<time_t>(params[2]) : Anope::CurTime, params[3], params[7], na ? *na->nc : NULL);
User::OnIntroduce(params[0], params[4], (params[8] != "*" ? params[8] : params[5]), params[5], params[6], source.GetServer(), params[10], params[2].is_pos_number_only() ? convertTo<time_t>(params[2]) : Anope::CurTime, params[3], params[7], na ? *na->nc : NULL);
}
};
+1 -1
View File
@@ -406,7 +406,7 @@ class InspIRCd12Proto : public IRCDProto
UplinkSocket::Message(Me) << "ENCAP " << message.target.substr(0, 3) << " SASL " << message.source << " " << message.target << " " << message.type << " " << message.data << (message.ext.empty() ? "" : (" " + message.ext));
}
void SendSVSLogin(const Anope::string &uid, const Anope::string &acc) anope_override
void SendSVSLogin(const Anope::string &uid, const Anope::string &acc, const Anope::string &vident, const Anope::string &vhost) anope_override
{
UplinkSocket::Message(Me) << "METADATA " << uid << " accountname :" << acc;
+27 -1
View File
@@ -42,6 +42,15 @@ class InspIRCd20Proto : public IRCDProto
insp12->SendConnect();
}
void SendSASLMechanisms(std::vector<Anope::string> &mechanisms) anope_override
{
Anope::string mechlist;
for (unsigned i = 0; i < mechanisms.size(); ++i)
mechlist += "," + mechanisms[i];
UplinkSocket::Message(Me) << "METADATA * saslmechlist :" << (mechanisms.empty() ? "" : mechlist.substr(1));
}
void SendSVSKillInternal(const MessageSource &source, User *user, const Anope::string &buf) anope_override { insp12->SendSVSKillInternal(source, user, buf); }
void SendGlobalNotice(BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override { insp12->SendGlobalNotice(bi, dest, msg); }
void SendGlobalPrivmsg(BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override { insp12->SendGlobalPrivmsg(bi, dest, msg); }
@@ -72,11 +81,26 @@ class InspIRCd20Proto : public IRCDProto
void SendLogout(User *u) anope_override { insp12->SendLogout(u); }
void SendChannel(Channel *c) anope_override { insp12->SendChannel(c); }
void SendSASLMessage(const SASL::Message &message) anope_override { insp12->SendSASLMessage(message); }
void SendSVSLogin(const Anope::string &uid, const Anope::string &acc) anope_override { insp12->SendSVSLogin(uid, acc); }
void SendSVSLogin(const Anope::string &uid, const Anope::string &acc, const Anope::string &vident, const Anope::string &vhost) anope_override { insp12->SendSVSLogin(uid, acc, vident, vhost); }
bool IsExtbanValid(const Anope::string &mask) anope_override { return insp12->IsExtbanValid(mask); }
bool IsIdentValid(const Anope::string &ident) anope_override { return insp12->IsIdentValid(ident); }
};
class InspIRCdAutoOpMode : public ChannelModeList
{
public:
InspIRCdAutoOpMode(char mode) : ChannelModeList("AUTOOP", mode)
{
}
bool IsValid(Anope::string &mask) const anope_override
{
// We can not validate this because we don't know about the
// privileges of the setter so just reject attempts to set it.
return false;
}
};
class InspIRCdExtBan : public ChannelModeVirtual<ChannelModeList>
{
char ext;
@@ -395,6 +419,8 @@ struct IRCDMessageCapab : Message::Capab
}
else if (modename.equals_cs("auditorium"))
cm = new ChannelMode("AUDITORIUM", modechar[0]);
else if (modename.equals_cs("autoop"))
cm = new InspIRCdAutoOpMode(modechar[0]);
else if (modename.equals_cs("ban"))
cm = new ChannelModeList("BAN", modechar[0]);
else if (modename.equals_cs("banexception"))
+5 -2
View File
@@ -280,7 +280,7 @@ struct IRCDMessageChaninfo : IRCDMessage
struct IRCDMessageJoin : Message::Join
{
IRCDMessageJoin(Module *creator) : Message::Join(creator, "JOIN") { }
IRCDMessageJoin(Module *creator) : Message::Join(creator, "JOIN") { SetFlag(IRCDMESSAGE_REQUIRE_USER); }
/*
* <@po||ux> DukeP: RFC 2813, 4.2.1: the JOIN command on server-server links
@@ -440,8 +440,11 @@ struct IRCDMessageNick : IRCDMessage
{
if (params.size() == 1)
{
User *u = source.GetUser();
// we have a nickchange
source.GetUser()->ChangeNick(params[0]);
if (u)
u->ChangeNick(params[0]);
}
else if (params.size() == 7)
{
+25 -6
View File
@@ -139,6 +139,25 @@ struct IRCDMessageEncap : IRCDMessage
}
};
struct IRCDMessageJoin : Message::Join
{
IRCDMessageJoin(Module *creator) : Message::Join(creator, "JOIN") { }
void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
{
if (params.size() == 1 && params[0] == "0")
return Message::Join::Run(source, params);
if (params.size() < 2)
return;
std::vector<Anope::string> p = params;
p.erase(p.begin());
return Message::Join::Run(source, p);
}
};
struct IRCDMessagePass : IRCDMessage
{
IRCDMessagePass(Module *creator) : IRCDMessage(creator, "PASS", 4) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); }
@@ -229,11 +248,12 @@ class ProtoRatbox : public Module
Message::Whois message_whois;
/* Hybrid message handlers */
ServiceAlias message_bmask, message_join, message_nick, message_pong, message_sid,
ServiceAlias message_bmask, message_nick, message_pong, message_sid,
message_sjoin, message_tmode;
/* Our message handlers */
IRCDMessageEncap message_encap;
IRCDMessageJoin message_join;
IRCDMessagePass message_pass;
IRCDMessageServer message_server;
IRCDMessageTBurst message_tburst;
@@ -296,12 +316,11 @@ class ProtoRatbox : public Module
message_ping(this), message_privmsg(this), message_quit(this), message_squit(this), message_stats(this),
message_time(this), message_topic(this), message_version(this), message_whois(this),
message_bmask("IRCDMessage", "ratbox/bmask", "hybrid/bmask"), message_join("IRCDMessage", "ratbox/join", "hybrid/join"),
message_nick("IRCDMessage", "ratbox/nick", "hybrid/nick"), message_pong("IRCDMessage", "ratbox/pong", "hybrid/pong"),
message_sid("IRCDMessage", "ratbox/sid", "hybrid/sid"), message_sjoin("IRCDMessage", "ratbox/sjoin", "hybrid/sjoin"),
message_tmode("IRCDMessage", "ratbox/tmode", "hybrid/tmode"),
message_bmask("IRCDMessage", "ratbox/bmask", "hybrid/bmask"), message_nick("IRCDMessage", "ratbox/nick", "hybrid/nick"),
message_pong("IRCDMessage", "ratbox/pong", "hybrid/pong"), message_sid("IRCDMessage", "ratbox/sid", "hybrid/sid"),
message_sjoin("IRCDMessage", "ratbox/sjoin", "hybrid/sjoin"), message_tmode("IRCDMessage", "ratbox/tmode", "hybrid/tmode"),
message_encap(this), message_pass(this), message_server(this), message_tburst(this), message_uid(this)
message_encap(this), message_join(this), message_pass(this), message_server(this), message_tburst(this), message_uid(this)
{
if (ModuleManager::LoadModule("hybrid", User::Find(creator)) != MOD_ERR_OK)
+6 -2
View File
@@ -386,7 +386,7 @@ class UnrealIRCdProto : public IRCDProto
UplinkSocket::Message(BotInfo::Find(message.source)) << "SASL " << message.target.substr(0, p) << " " << message.target << " " << message.type << " " << message.data << (message.ext.empty() ? "" : " " + message.ext);
}
void SendSVSLogin(const Anope::string &uid, const Anope::string &acc) anope_override
void SendSVSLogin(const Anope::string &uid, const Anope::string &acc, const Anope::string &vident, const Anope::string &vhost) anope_override
{
size_t p = uid.find('!');
if (p == Anope::string::npos)
@@ -929,7 +929,11 @@ struct IRCDMessageNick : IRCDMessage
User::OnIntroduce(params[0], params[3], params[4], vhost, ip, s, params[10], user_ts, params[7], "", na ? *na->nc : NULL);
}
else
source.GetUser()->ChangeNick(params[0]);
{
User *u = source.GetUser();
if (u)
u->ChangeNick(params[0]);
}
}
};
+7 -3
View File
@@ -374,7 +374,7 @@ class UnrealIRCdProto : public IRCDProto
UplinkSocket::Message(BotInfo::Find(message.source)) << "SASL " << message.target.substr(0, p) << " " << message.target << " " << message.type << " " << message.data << (message.ext.empty() ? "" : " " + message.ext);
}
void SendSVSLogin(const Anope::string &uid, const Anope::string &acc) anope_override
void SendSVSLogin(const Anope::string &uid, const Anope::string &acc, const Anope::string &vident, const Anope::string &vhost) anope_override
{
size_t p = uid.find('!');
if (p == Anope::string::npos)
@@ -966,7 +966,11 @@ struct IRCDMessageNick : IRCDMessage
User::OnIntroduce(params[0], params[3], params[4], vhost, ip, s, params[10], user_ts, params[7], "", na ? *na->nc : NULL);
}
else
source.GetUser()->ChangeNick(params[0]);
{
User *u = source.GetUser();
if (u)
u->ChangeNick(params[0]);
}
}
};
@@ -1279,7 +1283,7 @@ struct IRCDMessageUID : IRCDMessage
User *u = User::OnIntroduce(nickname, username, hostname, vhost, ip, source.GetServer(), info, user_ts, umodes, uid, na ? *na->nc : NULL);
if (!chost.empty() && chost != u->GetCloakedHost())
if (u && !chost.empty() && chost != u->GetCloakedHost())
u->SetCloakedHost(chost);
}
};
+1
View File
@@ -67,6 +67,7 @@ class MemoServCore : public Module, public MemoServService
sender->lastmemosend = Anope::CurTime;
Memo *m = new Memo();
m->mi = mi;
mi->memos->push_back(m);
m->owner = target;
m->sender = source;
+5
View File
@@ -97,7 +97,12 @@ class SQLineManager : public XLineManager
u->Kill(Config->GetClient("OperServ"), "Q-Lined: " + x->reason);
}
else if (x->mask[0] != '#' || IRCD->CanSQLineChannel)
{
IRCD->SendSQLine(u, x);
/* If it is an oper, assume they're walking it, otherwise kill for good measure */
if (u && !u->HasMode("OPER"))
u->Kill(Config->GetClient("OperServ"), "Q-Lined: " + x->reason);
}
}
void SendDel(XLine *x) anope_override
+3 -4
View File
@@ -46,10 +46,9 @@ bool WebCPanel::NickServ::Alist::OnRequest(HTTPProvider *server, const Anope::st
replacements["NUMBERS"] = stringify(chan_count);
replacements["CHANNELS"] = (ci->HasExt("CS_NO_EXPIRE") ? "!" : "") + ci->name;
Anope::string access_str;
for (unsigned i = 0; i < access.size(); ++i)
access_str += ", " + access[i]->AccessSerialize();
replacements["ACCESSES"] = access_str.substr(2);
const ChanAccess *highest = access.Highest();
replacements["ACCESSES"] = highest ? highest->AccessSerialize() : "";
}
TemplateFileServer page("nickserv/alist.html");
+42 -51
View File
@@ -250,8 +250,10 @@ Serializable* ChanAccess::Unserialize(Serializable *obj, Serialize::Data &data)
return access;
}
bool ChanAccess::Matches(const User *u, const NickCore *acc, Path &p) const
bool ChanAccess::Matches(const User *u, const NickCore *acc, ChannelInfo* &next) const
{
next = NULL;
if (this->nc)
return this->nc == acc;
@@ -276,28 +278,7 @@ bool ChanAccess::Matches(const User *u, const NickCore *acc, Path &p) const
if (IRCD->IsChannelValid(this->mask))
{
ChannelInfo *tci = ChannelInfo::Find(this->mask);
if (tci)
{
for (unsigned i = 0; i < tci->GetAccessCount(); ++i)
{
ChanAccess *a = tci->GetAccess(i);
std::pair<const ChanAccess *, const ChanAccess *> pair = std::make_pair(this, a);
std::pair<Set::iterator, Set::iterator> range = p.first.equal_range(this);
for (; range.first != range.second; ++range.first)
if (range.first->first == pair.first && range.first->second == pair.second)
goto cont;
p.first.insert(pair);
if (a->Matches(u, acc, p))
p.second.insert(pair);
cont:;
}
return p.second.count(this) > 0;
}
next = ChannelInfo::Find(this->mask);
}
return false;
@@ -347,37 +328,30 @@ bool ChanAccess::operator<=(const ChanAccess &other) const
return !(*this > other);
}
AccessGroup::AccessGroup() : std::vector<ChanAccess *>()
AccessGroup::AccessGroup()
{
this->ci = NULL;
this->nc = NULL;
this->super_admin = this->founder = false;
}
static bool HasPriv(const AccessGroup &ag, const ChanAccess *access, const Anope::string &name)
static bool HasPriv(const ChanAccess::Path &path, const Anope::string &name)
{
EventReturn MOD_RESULT;
FOREACH_RESULT(OnCheckPriv, MOD_RESULT, (access, name));
if (MOD_RESULT == EVENT_ALLOW || access->HasPriv(name))
if (path.empty())
return false;
for (unsigned int i = 0; i < path.size(); ++i)
{
typedef std::multimap<const ChanAccess *, const ChanAccess *> path;
std::pair<path::const_iterator, path::const_iterator> it = ag.path.second.equal_range(access);
if (it.first != it.second)
/* check all of the paths for this entry */
for (; it.first != it.second; ++it.first)
{
const ChanAccess *a = it.first->second;
/* if only one path fully matches then we are ok */
if (HasPriv(ag, a, name))
return true;
}
else
/* entry is the end of a chain, all entries match, ok */
return true;
ChanAccess *access = path[i];
EventReturn MOD_RESULT;
FOREACH_RESULT(OnCheckPriv, MOD_RESULT, (access, name));
if (MOD_RESULT != EVENT_ALLOW && !access->HasPriv(name))
return false;
}
/* entry does not match or none of the chains fully match */
return false;
return true;
}
bool AccessGroup::HasPriv(const Anope::string &name) const
@@ -393,7 +367,7 @@ bool AccessGroup::HasPriv(const Anope::string &name) const
bool auto_mode = !name.find("AUTO");
/* Only grant founder privilege if this isn't an auto mode or if they don't match any entries in this group */
if ((!auto_mode || this->empty()) && this->founder)
if ((!auto_mode || paths.empty()) && this->founder)
return true;
EventReturn MOD_RESULT;
@@ -401,23 +375,40 @@ bool AccessGroup::HasPriv(const Anope::string &name) const
if (MOD_RESULT != EVENT_CONTINUE)
return MOD_RESULT == EVENT_ALLOW;
for (unsigned i = this->size(); i > 0; --i)
for (unsigned int i = paths.size(); i > 0; --i)
{
ChanAccess *access = this->at(i - 1);
const ChanAccess::Path &path = paths[i - 1];
if (::HasPriv(*this, access, name))
if (::HasPriv(path, name))
return true;
}
return false;
}
static ChanAccess *HighestInPath(const ChanAccess::Path &path)
{
ChanAccess *highest = NULL;
for (unsigned int i = 0; i < path.size(); ++i)
if (highest == NULL || *path[i] > *highest)
highest = path[i];
return highest;
}
const ChanAccess *AccessGroup::Highest() const
{
ChanAccess *highest = NULL;
for (unsigned i = 0; i < this->size(); ++i)
if (highest == NULL || *this->at(i) > *highest)
highest = this->at(i);
for (unsigned int i = 0; i < paths.size(); ++i)
{
ChanAccess *hip = HighestInPath(paths[i]);
if (highest == NULL || *hip > *highest)
highest = hip;
}
return highest;
}
+7 -2
View File
@@ -168,8 +168,7 @@ void Channel::DeleteUser(User *user)
Log(LOG_DEBUG) << "Channel::DeleteUser() tried to delete non-existent channel " << this->name << " from " << user->nick << "'s channel list";
delete cu;
if (std::find(deleting.begin(), deleting.end(), this) == deleting.end())
deleting.push_back(this);
QueueForDeletion();
}
ChanUserContainer *Channel::FindUser(User *u) const
@@ -938,6 +937,12 @@ Channel *Channel::FindOrCreate(const Anope::string &name, bool &created, time_t
return chan;
}
void Channel::QueueForDeletion()
{
if (std::find(deleting.begin(), deleting.end(), this) == deleting.end())
deleting.push_back(this);
}
void Channel::DeleteChannels()
{
for (unsigned int i = 0; i < deleting.size(); ++i)
+1 -1
View File
@@ -117,7 +117,7 @@ void CommandSource::Reply(const Anope::string &message)
this->reply->SendMessage(this->service, tok);
}
Command::Command(Module *o, const Anope::string &sname, size_t minparams, size_t maxparams) : Service(o, "Command", sname), max_params(maxparams), min_params(minparams), module(owner)
Command::Command(Module *o, const Anope::string &sname, size_t minparams, size_t maxparams) : Service(o, "Command", sname), max_params(maxparams), min_params(minparams), module(o)
{
allow_unregistered = require_user = false;
}
+8
View File
@@ -75,6 +75,10 @@ const char *Language::Translate(const NickCore *nc, const char *string)
#if GETTEXT_FOUND
#ifdef __USE_GNU_GETTEXT
extern "C" int _nl_msg_cat_cntr;
#endif
const char *Language::Translate(const char *lang, const char *string)
{
if (!string || !*string)
@@ -83,6 +87,10 @@ const char *Language::Translate(const char *lang, const char *string)
if (!lang || !*lang)
lang = Config->DefLanguage.c_str();
#ifdef __USE_GNU_GETTEXT
++_nl_msg_cat_cntr;
#endif
#ifdef _WIN32
SetThreadLocale(MAKELCID(MAKELANGID(WindowsGetLanguage(lang), SUBLANG_DEFAULT), SORT_DEFAULT));
#else
+12 -3
View File
@@ -19,13 +19,12 @@
Memo::Memo() : Serializable("Memo")
{
mi = NULL;
unread = receipt = false;
}
Memo::~Memo()
{
bool ischan;
MemoInfo *mi = MemoInfo::GetMemoInfo(this->owner, ischan);
if (mi)
{
std::vector<Memo *>::iterator it = std::find(mi->memos->begin(), mi->memos->end(), this);
@@ -60,7 +59,10 @@ Serializable* Memo::Unserialize(Serializable *obj, Serialize::Data &data)
if (obj)
m = anope_dynamic_static_cast<Memo *>(obj);
else
{
m = new Memo();
m->mi = mi;
}
m->owner = owner;
data["time"] >> m->time;
@@ -99,7 +101,14 @@ void MemoInfo::Del(unsigned index)
{
if (index >= this->memos->size())
return;
delete this->GetMemo(index);
Memo *m = this->GetMemo(index);
std::vector<Memo *>::iterator it = std::find(memos->begin(), memos->end(), m);
if (it != memos->end())
memos->erase(it);
delete m;
}
bool MemoInfo::HasIgnore(User *u)
+1 -1
View File
@@ -162,7 +162,7 @@ void Join::SJoin(MessageSource &source, const Anope::string &chan, time_t ts, co
c->Sync();
if (c->CheckDelete())
delete c;
c->QueueForDeletion();
}
}
}
+5 -1
View File
@@ -320,7 +320,7 @@ Anope::string Anope::Duration(time_t t, const NickCore *nc)
time_t minutes = (t / 60) % 60;
time_t seconds = (t) % 60;
if (!days && !hours && !minutes)
if (!years && !days && !hours && !minutes)
return stringify(seconds) + " " + (seconds != 1 ? Language::Translate(nc, _("seconds")) : Language::Translate(nc, _("second")));
else
{
@@ -632,7 +632,11 @@ Anope::string Anope::VersionShort()
Anope::string Anope::VersionBuildString()
{
#ifdef REPRODUCIBLE_BUILD
Anope::string s = "build #" + stringify(BUILD);
#else
Anope::string s = "build #" + stringify(BUILD) + ", compiled " + Anope::compiled;
#endif
Anope::string flags;
#ifdef DEBUG_BUILD
+20 -8
View File
@@ -742,7 +742,7 @@ void ModeManager::StackerDel(Mode *m)
}
}
Entry::Entry(const Anope::string &m, const Anope::string &fh) : name(m), mask(fh), cidr_len(0)
Entry::Entry(const Anope::string &m, const Anope::string &fh) : name(m), mask(fh), cidr_len(0), family(0)
{
Anope::string n, u, h;
@@ -802,14 +802,13 @@ Entry::Entry(const Anope::string &m, const Anope::string &fh) : name(m), mask(fh
if (addr.valid() && cidr_range.is_pos_number_only())
{
this->cidr_len = convertTo<unsigned short>(cidr_range);
/* If we got here, cidr_len is a valid number.
* If cidr_len is >32 (or 128) it is handled later in
* cidr::match
*/
/* If we got here, cidr_len is a valid number. */
this->host = cidr_ip;
this->family = addr.family();
Log(LOG_DEBUG) << "Ban " << m << " has cidr " << this->cidr_len;
Log(LOG_DEBUG) << "Ban " << mask << " has cidr " << this->cidr_len;
}
}
catch (const ConvertException &) { }
@@ -830,8 +829,21 @@ const Anope::string Entry::GetNUHMask() const
Anope::string n = nick.empty() ? "*" : nick,
u = user.empty() ? "*" : user,
h = host.empty() ? "*" : host,
r = real.empty() ? "" : "#" + real;
return n + "!" + u + "@" + h + r;
r = real.empty() ? "" : "#" + real,
c;
switch (family)
{
case AF_INET:
if (cidr_len <= 32)
c = "/" + stringify(cidr_len);
break;
case AF_INET6:
if (cidr_len <= 128)
c = "/" + stringify(cidr_len);
break;
}
return n + "!" + u + "@" + h + c + r;
}
bool Entry::Matches(User *u, bool full) const
+69 -35
View File
@@ -157,7 +157,7 @@ ChannelInfo::~ChannelInfo()
if (this->c)
{
if (this->c && this->c->CheckDelete())
delete this->c;
this->c->QueueForDeletion();
this->c = NULL;
}
@@ -384,6 +384,39 @@ ChanAccess *ChannelInfo::GetAccess(unsigned index) const
return acc;
}
static void FindMatchesRecurse(ChannelInfo *ci, const User *u, const NickCore *account, unsigned int depth, std::vector<ChanAccess::Path> &paths, ChanAccess::Path &path)
{
if (depth > ChanAccess::MAX_DEPTH)
return;
for (unsigned int i = 0; i < ci->GetAccessCount(); ++i)
{
ChanAccess *a = ci->GetAccess(i);
ChannelInfo *next = NULL;
if (a->Matches(u, account, next))
{
ChanAccess::Path next_path = path;
next_path.push_back(a);
paths.push_back(next_path);
}
else if (next)
{
ChanAccess::Path next_path = path;
next_path.push_back(a);
FindMatchesRecurse(next, u, account, depth + 1, paths, next_path);
}
}
}
static void FindMatches(AccessGroup &group, ChannelInfo *ci, const User *u, const NickCore *account)
{
ChanAccess::Path path;
FindMatchesRecurse(ci, u, account, 0, group.paths, path);
}
AccessGroup ChannelInfo::AccessFor(const User *u, bool updateLastUsed)
{
AccessGroup group;
@@ -404,20 +437,20 @@ AccessGroup ChannelInfo::AccessFor(const User *u, bool updateLastUsed)
group.ci = this;
group.nc = nc;
for (unsigned i = 0, end = this->GetAccessCount(); i < end; ++i)
{
ChanAccess *a = this->GetAccess(i);
if (a->Matches(u, u->Account(), group.path))
group.push_back(a);
}
FindMatches(group, this, u, u->Account());
if (group.founder || !group.empty())
if (group.founder || !group.paths.empty())
{
if (updateLastUsed)
this->last_used = Anope::CurTime;
for (unsigned i = 0; i < group.size(); ++i)
group[i]->last_seen = Anope::CurTime;
for (unsigned i = 0; i < group.paths.size(); ++i)
{
ChanAccess::Path &p = group.paths[i];
for (unsigned int j = 0; j < p.size(); ++j)
p[j]->last_seen = Anope::CurTime;
}
}
return group;
@@ -431,14 +464,9 @@ AccessGroup ChannelInfo::AccessFor(const NickCore *nc, bool updateLastUsed)
group.ci = this;
group.nc = nc;
for (unsigned i = 0, end = this->GetAccessCount(); i < end; ++i)
{
ChanAccess *a = this->GetAccess(i);
if (a->Matches(NULL, nc, group.path))
group.push_back(a);
}
FindMatches(group, this, NULL, nc);
if (group.founder || !group.empty())
if (group.founder || !group.paths.empty())
if (updateLastUsed)
this->last_used = Anope::CurTime;
@@ -452,28 +480,34 @@ unsigned ChannelInfo::GetAccessCount() const
return this->access->size();
}
unsigned ChannelInfo::GetDeepAccessCount() const
static unsigned int GetDeepAccessCount(const ChannelInfo *ci, std::set<const ChannelInfo *> &seen, unsigned int depth)
{
ChanAccess::Path path;
for (unsigned i = 0, end = this->GetAccessCount(); i < end; ++i)
if (depth > ChanAccess::MAX_DEPTH || seen.count(ci))
return 0;
seen.insert(ci);
unsigned int total = 0;
for (unsigned int i = 0; i < ci->GetAccessCount(); ++i)
{
ChanAccess *a = this->GetAccess(i);
a->Matches(NULL, NULL, path);
ChanAccess::Path path;
ChanAccess *a = ci->GetAccess(i);
ChannelInfo *next = NULL;
a->Matches(NULL, NULL, next);
++total;
if (next)
total += GetDeepAccessCount(ci, seen, depth + 1);
}
unsigned count = this->GetAccessCount();
std::set<const ChannelInfo *> channels;
channels.insert(this);
for (ChanAccess::Set::iterator it = path.first.begin(); it != path.first.end(); ++it)
{
const ChannelInfo *ci = it->first->ci;
if (!channels.count(ci))
{
channels.count(ci);
count += ci->GetAccessCount();
}
}
return count;
return total;
}
unsigned ChannelInfo::GetDeepAccessCount() const
{
std::set<const ChannelInfo *> seen;
return ::GetDeepAccessCount(this, seen, 0);
}
ChanAccess *ChannelInfo::EraseAccess(unsigned index)
+5
View File
@@ -39,6 +39,11 @@ void sockaddrs::clear()
memset(this, 0, sizeof(*this));
}
int sockaddrs::family() const
{
return sa.sa_family;
}
size_t sockaddrs::size() const
{
switch (sa.sa_family)
+1 -1
View File
@@ -48,5 +48,5 @@ endif(NOT WIN32)
# On non-Windows platforms, if RUNGROUP is set, change the permissions of the tools directory
if(NOT WIN32 AND RUNGROUP)
install(CODE "execute_process(COMMAND ${CHMOD} 2770 \"\$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin\")")
install(CODE "execute_process(COMMAND ${CHMOD} 2770 \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/bin\")")
endif(NOT WIN32 AND RUNGROUP)
+2
View File
@@ -507,6 +507,8 @@ void User::UpdateHost()
Anope::string last_realhost = this->GetIdent() + "@" + this->host;
na->last_usermask = last_usermask;
na->last_realhost = last_realhost;
// This is called on signon, and if users are introduced with an account it won't update
na->last_realname = this->realname;
}
}
+1 -1
View File
@@ -2,6 +2,6 @@
VERSION_MAJOR=2
VERSION_MINOR=0
VERSION_PATCH=3
VERSION_PATCH=4
VERSION_EXTRA=""