summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/users.h196
-rw-r--r--src/channels.cpp28
-rw-r--r--src/command_parse.cpp10
-rw-r--r--src/commands/cmd_invite.cpp7
-rw-r--r--src/commands/cmd_nick.cpp3
-rw-r--r--src/commands/cmd_oper.cpp2
-rw-r--r--src/commands/cmd_pass.cpp8
-rw-r--r--src/commands/cmd_pong.cpp3
-rw-r--r--src/modules/extra/m_ldapauth.cpp7
-rw-r--r--src/modules/m_cgiirc.cpp4
-rw-r--r--src/modules/m_cloaking.cpp2
-rw-r--r--src/modules/m_override.cpp2
-rw-r--r--src/modules/m_sqlauth.cpp2
-rw-r--r--src/modules/m_testnet.cpp4
-rw-r--r--src/modules/m_uninvite.cpp31
-rw-r--r--src/usermanager.cpp8
-rw-r--r--src/users.cpp198
17 files changed, 275 insertions, 240 deletions
diff --git a/include/users.h b/include/users.h
index 0be98f3bf..51600e3af 100644
--- a/include/users.h
+++ b/include/users.h
@@ -235,12 +235,6 @@ class User;
class CoreExport User : public StreamSocket
{
private:
- /** A list of channels the user has a pending invite to.
- * Upon INVITE channels are added, and upon JOIN, the
- * channels are removed from this list.
- */
- InvitedList invites;
-
/** Cached nick!ident@dhost value using the displayed hostname
*/
std::string cached_fullhost;
@@ -266,30 +260,13 @@ class CoreExport User : public StreamSocket
* mode characters this user is making use of.
*/
void DecrementModes();
-
- std::set<std::string> *AllowedOperCommands;
- std::set<std::string> *AllowedPrivs;
-
- /** Allowed user modes from oper classes. */
- std::bitset<64> AllowedUserModes;
-
- /** Allowed channel modes from oper classes. */
- std::bitset<64> AllowedChanModes;
-
public:
- /** Contains a pointer to the connect class a user is on from - this will be NULL for remote connections.
- */
- reference<ConnectClass> MyClass;
/** Hostname of connection.
* This should be valid as per RFC1035.
*/
std::string host;
- /** Time the connection was last pinged
- */
- time_t lastping;
-
/** Time that the object was instantiated (used for TS calculation etc)
*/
time_t age;
@@ -304,20 +281,12 @@ class CoreExport User : public StreamSocket
*/
time_t idle_lastmsg;
- /** Used by PING checking code
- */
- time_t nping;
-
/** Client address that the user is connected from.
* Do not modify this value directly, use SetClientIP() to change it
* Port is not valid for remote users.
*/
irc::sockets::sockaddrs client_sa;
- /** Stored reverse lookup from res_forward. Should not be used after resolution.
- */
- std::string stored_host;
-
/** The users nickname.
* An invalid nickname indicates an unregistered connection prior to the NICK command.
* Use InspIRCd::IsNick() to validate nicknames.
@@ -360,7 +329,7 @@ class CoreExport User : public StreamSocket
*/
std::bitset<64> snomasks;
- /** Channels this user is on, and the permissions they have there
+ /** Channels this user is on
*/
UserChanList chans;
@@ -380,22 +349,11 @@ class CoreExport User : public StreamSocket
/** The oper type they logged in as, if they are an oper.
* This is used to check permissions in operclasses, so that
- * we can say 'yay' or 'nay' to any commands they issue.
- * The value of this is the value of a valid 'type name=' tag.
+ * we can say 'yea' or 'nay' to any commands they issue.
+ * The value of this was the value of a valid 'type name=' tag
*/
std::string oper;
- /** Password specified by the user when they registered.
- * This is stored even if the <connect> block doesnt need a password, so that
- * modules may check it.
- */
- std::string password;
-
- /** This value contains how far into the penalty threshold the user is. Once its over
- * the penalty threshold then commands are held and processed on-timer.
- */
- int Penalty;
-
/** Used by User to indicate the registration status of the connection
* It is a bitfield of the REG_NICK, REG_USER and REG_ALL bits to indicate
* the connection state.
@@ -423,6 +381,10 @@ class CoreExport User : public StreamSocket
*/
unsigned int exempt:1;
+ /** has the user responded to their previous ping?
+ */
+ unsigned int lastping:1;
+
/** Get client IP string from sockaddr, using static internal buffer
* @return The IP string
*/
@@ -517,32 +479,13 @@ class CoreExport User : public StreamSocket
*/
void SetMode(unsigned char m, bool value);
- /** Returns true if a user is invited to a channel.
- * @param channel A channel name to look up
- * @return True if the user is invited to the given channel
- */
- virtual bool IsInvited(const irc::string &channel);
-
- /** Adds a channel to a users invite list (invites them to a channel)
- * @param channel A channel name to add
- * @param timeout When the invite should expire (0 == never)
- */
- virtual void InviteTo(const irc::string &channel, time_t timeout);
-
- /** Removes a channel from a users invite list.
- * This member function is called on successfully joining an invite only channel
- * to which the user has previously been invited, to clear the invitation.
- * @param channel The channel to remove the invite to
- */
- virtual void RemoveInvite(const irc::string &channel);
-
/** Returns true or false for if a user can execute a privilaged oper command.
* This is done by looking up their oper type from User::oper, then referencing
* this to their oper classes and checking the commands they can execute.
* @param command A command (should be all CAPS)
* @return True if this user can execute the command
*/
- bool HasPermission(const std::string &command);
+ virtual bool HasPermission(const std::string &command);
/** Returns true if a user has a given permission.
* This is used to check whether or not users may perform certain actions which admins may not wish to give to
@@ -552,7 +495,7 @@ class CoreExport User : public StreamSocket
* @param noisy If set to true, the user is notified that they do not have the specified permission where applicable. If false, no notification is sent.
* @return True if this user has the permission in question.
*/
- bool HasPrivPermission(const std::string &privstr, bool noisy = false);
+ virtual bool HasPrivPermission(const std::string &privstr, bool noisy = false);
/** Returns true or false if a user can set a privileged user or channel mode.
* This is done by looking up their oper type from User::oper, then referencing
@@ -561,12 +504,7 @@ class CoreExport User : public StreamSocket
* @param type ModeType (MODETYPE_CHANNEL or MODETYPE_USER).
* @return True if the user can set or unset this mode.
*/
- bool HasModePermission(unsigned char mode, ModeType type);
-
- /** Returns the list of channels this user has been invited to but has not yet joined.
- * @return A list of channels the user is invited to
- */
- InvitedList* GetInviteList();
+ virtual bool HasModePermission(unsigned char mode, ModeType type);
/** Creates a wildcard host.
* Takes a buffer to use and fills the given buffer with the host in the format *!*@hostname
@@ -596,10 +534,6 @@ class CoreExport User : public StreamSocket
*/
void Oper(const std::string &opertype, const std::string &opername);
- /** Call this method to find the matching <connect> for a user, and to check them against it.
- */
- void CheckClass();
-
/** Change this users hash key to a new string.
* You should not call this function directly. It is used by the core
* to update the users hash entry on a nickchange.
@@ -786,10 +720,10 @@ class CoreExport User : public StreamSocket
*/
void PurgeEmptyChannels();
- /** Get the connect class which this user belongs to.
- * @return A pointer to this user's connect class
+ /** Get the connect class which this user belongs to. NULL for remote users.
+ * @return A pointer to this user's connect class.
*/
- ConnectClass *GetClass();
+ virtual ConnectClass* GetClass();
/** Show the message of the day to this user
*/
@@ -799,10 +733,6 @@ class CoreExport User : public StreamSocket
*/
void ShowRULES();
- /** Increases a user's command penalty by a set amount.
- */
- void IncreasePenalty(int increase);
-
virtual void OnDataReady();
virtual void OnError(BufferedSocketError error);
/** Default destructor
@@ -821,6 +751,21 @@ class CoreExport User : public StreamSocket
class CoreExport LocalUser : public User
{
+ /** A list of channels the user has a pending invite to.
+ * Upon INVITE channels are added, and upon JOIN, the
+ * channels are removed from this list.
+ */
+ InvitedList invites;
+
+ std::set<std::string> *AllowedOperCommands;
+ std::set<std::string> *AllowedPrivs;
+
+ /** Allowed user modes from oper classes. */
+ std::bitset<64> AllowedUserModes;
+
+ /** Allowed channel modes from oper classes. */
+ std::bitset<64> AllowedChanModes;
+
public:
LocalUser();
CullResult cull();
@@ -841,6 +786,22 @@ class CoreExport LocalUser : public User
*/
int cmds_out;
+ /** Password specified by the user when they registered (if any).
+ * This is stored even if the <connect> block doesnt need a password, so that
+ * modules may check it.
+ */
+ std::string password;
+
+ /** Contains a pointer to the connect class a user is on from
+ */
+ reference<ConnectClass> MyClass;
+
+ ConnectClass* GetClass();
+
+ /** Call this method to find the matching <connect> for a user, and to check them against it.
+ */
+ void CheckClass();
+
/** Server address and port that this user is connected to.
*/
irc::sockets::sockaddrs server_sa;
@@ -850,6 +811,19 @@ class CoreExport LocalUser : public User
*/
int GetServerPort();
+ /** Used by PING checking code
+ */
+ time_t nping;
+
+ /** This value contains how far into the penalty threshold the user is. Once its over
+ * the penalty threshold then commands are held and processed on-timer.
+ */
+ int Penalty;
+
+ /** Stored reverse lookup from res_forward. Should not be used after resolution.
+ */
+ std::string stored_host;
+
/** Starts a DNS lookup of the user's IP.
* This will cause two UserResolver classes to be instantiated.
* When complete, these objects set User::dns_done to true.
@@ -865,7 +839,7 @@ class CoreExport LocalUser : public User
* @param explicit_name Set this string to tie the user to a specific class name. Otherwise, the class is fitted by checking <connect> tags from the configuration file.
* @return A reference to this user's current connect class.
*/
- ConnectClass *SetClass(const std::string &explicit_name = "");
+ void SetClass(const std::string &explicit_name = "");
void OnDataReady();
void SendText(const std::string& line);
@@ -878,6 +852,60 @@ class CoreExport LocalUser : public User
* @param data The data to add to the write buffer
*/
void AddWriteBuf(const std::string &data);
+
+ /** Returns the list of channels this user has been invited to but has not yet joined.
+ * @return A list of channels the user is invited to
+ */
+ InvitedList* GetInviteList();
+
+ /** Returns true if a user is invited to a channel.
+ * @param channel A channel name to look up
+ * @return True if the user is invited to the given channel
+ */
+ bool IsInvited(const irc::string &channel);
+
+ /** Adds a channel to a users invite list (invites them to a channel)
+ * @param channel A channel name to add
+ * @param timeout When the invite should expire (0 == never)
+ */
+ void InviteTo(const irc::string &channel, time_t timeout);
+
+ /** Removes a channel from a users invite list.
+ * This member function is called on successfully joining an invite only channel
+ * to which the user has previously been invited, to clear the invitation.
+ * @param channel The channel to remove the invite to
+ */
+ void RemoveInvite(const irc::string &channel);
+
+ /** Returns true or false for if a user can execute a privilaged oper command.
+ * This is done by looking up their oper type from User::oper, then referencing
+ * this to their oper classes and checking the commands they can execute.
+ * @param command A command (should be all CAPS)
+ * @return True if this user can execute the command
+ */
+ bool HasPermission(const std::string &command);
+
+ /** Returns true if a user has a given permission.
+ * This is used to check whether or not users may perform certain actions which admins may not wish to give to
+ * all operators, yet are not commands. An example might be oper override, mass messaging (/notice $*), etc.
+ *
+ * @param privstr The priv to chec, e.g. "users/override/topic". These are loaded free-form from the config file.
+ * @param noisy If set to true, the user is notified that they do not have the specified permission where applicable. If false, no notification is sent.
+ * @return True if this user has the permission in question.
+ */
+ bool HasPrivPermission(const std::string &privstr, bool noisy = false);
+
+ /** Returns true or false if a user can set a privileged user or channel mode.
+ * This is done by looking up their oper type from User::oper, then referencing
+ * this to their oper classes, and checking the modes they can set.
+ * @param mode The mode the check
+ * @param type ModeType (MODETYPE_CHANNEL or MODETYPE_USER).
+ * @return True if the user can set or unset this mode.
+ */
+ bool HasModePermission(unsigned char mode, ModeType type);
+
+ void OperInternal();
+ void UnOperInternal();
};
class CoreExport RemoteUser : public User
diff --git a/src/channels.cpp b/src/channels.cpp
index d7f8f372e..d0d8e52c5 100644
--- a/src/channels.cpp
+++ b/src/channels.cpp
@@ -218,24 +218,20 @@ Channel* Channel::JoinUser(User *user, const char* cn, bool override, const char
*/
if (IS_LOCAL(user) && !override)
{
- // Checking MyClass exists because we *may* get here with NULL, not 100% sure.
- if (user->MyClass && user->MyClass->maxchans)
+ if (user->HasPrivPermission("channels/high-join-limit"))
{
- if (user->HasPrivPermission("channels/high-join-limit"))
+ if (user->chans.size() >= ServerInstance->Config->OperMaxChans)
{
- if (user->chans.size() >= ServerInstance->Config->OperMaxChans)
- {
- user->WriteNumeric(ERR_TOOMANYCHANNELS, "%s %s :You are on too many channels",user->nick.c_str(), cn);
- return NULL;
- }
+ user->WriteNumeric(ERR_TOOMANYCHANNELS, "%s %s :You are on too many channels",user->nick.c_str(), cn);
+ return NULL;
}
- else
+ }
+ else
+ {
+ if (user->chans.size() >= user->GetClass()->maxchans)
{
- if (user->chans.size() >= user->MyClass->maxchans)
- {
- user->WriteNumeric(ERR_TOOMANYCHANNELS, "%s %s :You are on too many channels",user->nick.c_str(), cn);
- return NULL;
- }
+ user->WriteNumeric(ERR_TOOMANYCHANNELS, "%s %s :You are on too many channels",user->nick.c_str(), cn);
+ return NULL;
}
}
}
@@ -291,7 +287,7 @@ Channel* Channel::JoinUser(User *user, const char* cn, bool override, const char
else if (MOD_RESULT == MOD_RES_PASSTHRU)
{
std::string ckey = Ptr->GetModeParameter('k');
- bool invited = user->IsInvited(Ptr->name.c_str());
+ bool invited = IS_LOCAL(user)->IsInvited(Ptr->name.c_str());
bool can_bypass = ServerInstance->Config->InvBypassModes && invited;
if (!ckey.empty())
@@ -338,7 +334,7 @@ Channel* Channel::JoinUser(User *user, const char* cn, bool override, const char
*/
if (invited)
{
- user->RemoveInvite(Ptr->name.c_str());
+ IS_LOCAL(user)->RemoveInvite(Ptr->name.c_str());
}
}
}
diff --git a/src/command_parse.cpp b/src/command_parse.cpp
index 6dd4e663e..9fc8f85bb 100644
--- a/src/command_parse.cpp
+++ b/src/command_parse.cpp
@@ -249,11 +249,10 @@ bool CommandParser::ProcessCommand(User *user, std::string &cmd)
/* Modify the user's penalty regardless of whether or not the command exists */
bool do_more = true;
- if (!user->HasPrivPermission("users/flood/no-throttle"))
+ if (IS_LOCAL(user) && !user->HasPrivPermission("users/flood/no-throttle"))
{
// If it *doesn't* exist, give it a slightly heftier penalty than normal to deter flooding us crap
- user->IncreasePenalty(cm != cmdlist.end() ? cm->second->Penalty : 2);
- do_more = (user->GetClass()->GetPenaltyThreshold() && ((unsigned long)user->Penalty < user->GetClass()->GetPenaltyThreshold()));
+ IS_LOCAL(user)->Penalty += cm != cmdlist.end() ? cm->second->Penalty : 2;
}
@@ -328,8 +327,9 @@ bool CommandParser::ProcessCommand(User *user, std::string &cmd)
return true;
/* activity resets the ping pending timer */
- if (user->MyClass)
- user->nping = ServerInstance->Time() + user->MyClass->GetPingTime();
+ LocalUser* luser = IS_LOCAL(user);
+ if (luser)
+ luser->nping = ServerInstance->Time() + luser->MyClass->GetPingTime();
if (cm->second->flags_needed)
{
diff --git a/src/commands/cmd_invite.cpp b/src/commands/cmd_invite.cpp
index 9da6096a4..84c522754 100644
--- a/src/commands/cmd_invite.cpp
+++ b/src/commands/cmd_invite.cpp
@@ -90,7 +90,8 @@ CmdResult CommandInvite::Handle (const std::vector<std::string>& parameters, Use
}
}
- u->InviteTo(c->name.c_str(), timeout);
+ if (IS_LOCAL(u))
+ IS_LOCAL(u)->InviteTo(c->name.c_str(), timeout);
u->WriteFrom(user,"INVITE %s :%s",u->nick.c_str(),c->name.c_str());
user->WriteNumeric(RPL_INVITING, "%s %s %s",user->nick.c_str(),u->nick.c_str(),c->name.c_str());
switch (ServerInstance->Config->AnnounceInvites)
@@ -113,11 +114,11 @@ CmdResult CommandInvite::Handle (const std::vector<std::string>& parameters, Use
}
FOREACH_MOD(I_OnUserInvite,OnUserInvite(user,u,c,timeout));
}
- else
+ else if (IS_LOCAL(user))
{
// pinched from ircu - invite with not enough parameters shows channels
// youve been invited to but haven't joined yet.
- InvitedList* il = user->GetInviteList();
+ InvitedList* il = IS_LOCAL(user)->GetInviteList();
for (InvitedList::iterator i = il->begin(); i != il->end(); i++)
{
user->WriteNumeric(RPL_INVITELIST, "%s :%s",user->nick.c_str(),i->first.c_str());
diff --git a/src/commands/cmd_nick.cpp b/src/commands/cmd_nick.cpp
index ee8c4625c..489551dd1 100644
--- a/src/commands/cmd_nick.cpp
+++ b/src/commands/cmd_nick.cpp
@@ -202,7 +202,8 @@ CmdResult CommandNick::Handle (const std::vector<std::string>& parameters, User
if (user->registered == REG_ALL)
{
- user->IncreasePenalty(10);
+ if (IS_LOCAL(user))
+ IS_LOCAL(user)->Penalty += 10;
FOREACH_MOD(I_OnUserPostNick,OnUserPostNick(user, oldnick));
}
diff --git a/src/commands/cmd_oper.cpp b/src/commands/cmd_oper.cpp
index dc15a5415..428e7b109 100644
--- a/src/commands/cmd_oper.cpp
+++ b/src/commands/cmd_oper.cpp
@@ -124,7 +124,7 @@ CmdResult CommandOper::HandleLocal(const std::vector<std::string>& parameters, L
// tell them they suck, and lag them up to help prevent brute-force attacks
user->WriteNumeric(491, "%s :Invalid oper credentials",user->nick.c_str());
- user->IncreasePenalty(10);
+ user->Penalty += 10;
snprintf(broadcast, MAXBUF, "WARNING! Failed oper attempt by %s!%s@%s using login '%s': The following fields do not match: %s", user->nick.c_str(), user->ident.c_str(), user->host.c_str(), parameters[0].c_str(), fields.c_str());
ServerInstance->SNO->WriteToSnoMask('o',std::string(broadcast));
diff --git a/src/commands/cmd_pass.cpp b/src/commands/cmd_pass.cpp
index 21b5b2759..0bf1b46a4 100644
--- a/src/commands/cmd_pass.cpp
+++ b/src/commands/cmd_pass.cpp
@@ -18,23 +18,23 @@
* the same way, however, they can be fully unloaded, where these
* may not.
*/
-class CommandPass : public Command
+class CommandPass : public SplitCommand
{
public:
/** Constructor for pass.
*/
- CommandPass ( Module* parent) : Command(parent,"PASS",1,1) { works_before_reg = true; Penalty = 0; syntax = "<password>"; }
+ CommandPass (Module* parent) : SplitCommand(parent,"PASS",1,1) { works_before_reg = true; Penalty = 0; syntax = "<password>"; }
/** Handle command.
* @param parameters The parameters to the comamnd
* @param pcnt The number of parameters passed to teh command
* @param user The user issuing the command
* @return A value from CmdResult to indicate command success or failure.
*/
- CmdResult Handle(const std::vector<std::string>& parameters, User *user);
+ CmdResult HandleLocal(const std::vector<std::string>& parameters, LocalUser *user);
};
-CmdResult CommandPass::Handle (const std::vector<std::string>& parameters, User *user)
+CmdResult CommandPass::HandleLocal(const std::vector<std::string>& parameters, LocalUser *user)
{
// Check to make sure they haven't registered -- Fix by FCS
if (user->registered == REG_ALL)
diff --git a/src/commands/cmd_pong.cpp b/src/commands/cmd_pong.cpp
index 225be147a..9bff00ed2 100644
--- a/src/commands/cmd_pong.cpp
+++ b/src/commands/cmd_pong.cpp
@@ -36,7 +36,8 @@ class CommandPong : public Command
CmdResult CommandPong::Handle (const std::vector<std::string>&, User *user)
{
// set the user as alive so they survive to next ping
- user->lastping = 1;
+ if (IS_LOCAL(user))
+ IS_LOCAL(user)->lastping = 1;
return CMD_SUCCESS;
}
diff --git a/src/modules/extra/m_ldapauth.cpp b/src/modules/extra/m_ldapauth.cpp
index 26e968367..af676de44 100644
--- a/src/modules/extra/m_ldapauth.cpp
+++ b/src/modules/extra/m_ldapauth.cpp
@@ -127,17 +127,16 @@ public:
return MOD_RES_PASSTHRU;
}
- bool CheckCredentials(User* user)
+ bool CheckCredentials(LocalUser* user)
{
if (conn == NULL)
if (!Connect())
return false;
int res;
- char* authpass = strdup(password.c_str());
// bind anonymously if no bind DN and authentication are given in the config
struct berval cred;
- cred.bv_val = authpass;
+ cred.bv_val = const_cast<char*>(password.c_str());
cred.bv_len = password.length();
if ((res = ldap_sasl_bind_s(conn, username.c_str(), LDAP_SASL_SIMPLE, &cred, NULL, NULL, NULL)) != LDAP_SUCCESS)
@@ -155,13 +154,11 @@ public:
{
if (verbose)
ServerInstance->SNO->WriteToSnoMask('c', "Forbidden connection from %s!%s@%s (LDAP bind failed: %s)", user->nick.c_str(), user->ident.c_str(), user->host.c_str(), ldap_err2string(res));
- free(authpass);
ldap_unbind_ext(conn, NULL, NULL);
conn = NULL;
return false;
}
}
- free(authpass);
LDAPMessage *msg, *entry;
std::string what = (attribute + "=" + (useusername ? user->ident : user->nick));
diff --git a/src/modules/m_cgiirc.cpp b/src/modules/m_cgiirc.cpp
index 745dc13d2..5f8cfeca7 100644
--- a/src/modules/m_cgiirc.cpp
+++ b/src/modules/m_cgiirc.cpp
@@ -277,7 +277,7 @@ public:
}
}
- bool CheckPass(User* user)
+ bool CheckPass(LocalUser* user)
{
if(IsValidHost(user->password))
{
@@ -324,7 +324,7 @@ public:
return false;
}
- bool CheckIdent(User* user)
+ bool CheckIdent(LocalUser* user)
{
const char* ident;
int len = user->ident.length();
diff --git a/src/modules/m_cloaking.cpp b/src/modules/m_cloaking.cpp
index 0ad790de9..c0ebbc99b 100644
--- a/src/modules/m_cloaking.cpp
+++ b/src/modules/m_cloaking.cpp
@@ -57,7 +57,7 @@ class CloakUser : public ModeHandler
}
/* don't allow this user to spam modechanges */
- dest->IncreasePenalty(5);
+ IS_LOCAL(dest)->Penalty += 5;
if (adding)
{
diff --git a/src/modules/m_override.cpp b/src/modules/m_override.cpp
index e37282525..8a3fcdd62 100644
--- a/src/modules/m_override.cpp
+++ b/src/modules/m_override.cpp
@@ -135,7 +135,7 @@ class ModuleOverride : public Module
if ((chan->modes[CM_INVITEONLY]) && (CanOverride(user,"INVITE")))
{
irc::string x(chan->name.c_str());
- if (!user->IsInvited(x))
+ if (!IS_LOCAL(user)->IsInvited(x))
{
if (RequireKey && keygiven != "override")
{
diff --git a/src/modules/m_sqlauth.cpp b/src/modules/m_sqlauth.cpp
index a4c237e4e..3a4461480 100644
--- a/src/modules/m_sqlauth.cpp
+++ b/src/modules/m_sqlauth.cpp
@@ -85,7 +85,7 @@ public:
return MOD_RES_PASSTHRU;
}
- bool CheckCredentials(User* user)
+ bool CheckCredentials(LocalUser* user)
{
std::string thisquery = freeformquery;
std::string safepass = user->password;
diff --git a/src/modules/m_testnet.cpp b/src/modules/m_testnet.cpp
index 6a0cfa303..7f825a728 100644
--- a/src/modules/m_testnet.cpp
+++ b/src/modules/m_testnet.cpp
@@ -32,9 +32,9 @@ class CommandTest : public Command
for(unsigned int i=0; i < count; i++)
user->Write(line);
}
- else if (parameters[0] == "freeze")
+ else if (parameters[0] == "freeze" && IS_LOCAL(user))
{
- user->Penalty += 100;
+ IS_LOCAL(user)->Penalty += 100;
}
else if (parameters[0] == "shutdown")
{
diff --git a/src/modules/m_uninvite.cpp b/src/modules/m_uninvite.cpp
index 1215dd0df..fff51817e 100644
--- a/src/modules/m_uninvite.cpp
+++ b/src/modules/m_uninvite.cpp
@@ -56,28 +56,29 @@ class CommandUninvite : public Command
irc::string xname(c->name.c_str());
- if (!u->IsInvited(xname))
+ if (IS_LOCAL(u))
{
- user->WriteNumeric(505, "%s %s %s :Is not invited to channel %s", user->nick.c_str(), u->nick.c_str(), c->name.c_str(), c->name.c_str());
- return CMD_FAILURE;
- }
- if (!c->HasUser(user))
- {
- user->WriteNumeric(492, "%s %s :You're not on that channel!",user->nick.c_str(), c->name.c_str());
- return CMD_FAILURE;
+ // TODO send messages & such out to remote servers
+ LocalUser* lu = IS_LOCAL(u);
+ if (!lu->IsInvited(xname))
+ {
+ user->WriteNumeric(505, "%s %s %s :Is not invited to channel %s", user->nick.c_str(), u->nick.c_str(), c->name.c_str(), c->name.c_str());
+ return CMD_FAILURE;
+ }
+ user->WriteNumeric(494, "%s %s %s :Uninvited", user->nick.c_str(), c->name.c_str(), u->nick.c_str());
+ lu->RemoveInvite(xname);
+ lu->WriteNumeric(493, "%s :You were uninvited from %s by %s", u->nick.c_str(), c->name.c_str(), user->nick.c_str());
+ c->WriteChannelWithServ(ServerInstance->Config->ServerName, "NOTICE %s :*** %s uninvited %s.",
+ c->name.c_str(), user->nick.c_str(), u->nick.c_str());
}
- u->RemoveInvite(xname);
- user->WriteNumeric(494, "%s %s %s :Uninvited", user->nick.c_str(), c->name.c_str(), u->nick.c_str());
- u->WriteNumeric(493, "%s :You were uninvited from %s by %s", u->nick.c_str(), c->name.c_str(), user->nick.c_str());
- c->WriteChannelWithServ(ServerInstance->Config->ServerName.c_str(), "NOTICE %s :*** %s uninvited %s.", c->name.c_str(), user->nick.c_str(), u->nick.c_str());
-
return CMD_SUCCESS;
}
RouteDescriptor GetRouting(User* user, const std::vector<std::string>& parameters)
{
- return ROUTE_BROADCAST;
+ User* u = ServerInstance->FindNick(parameters[0]);
+ return u ? ROUTE_UNICAST(u->server) : ROUTE_LOCALONLY;
}
};
@@ -98,7 +99,7 @@ class ModuleUninvite : public Module
virtual Version GetVersion()
{
- return Version("Provides the UNINVITE command which lets users un-invite other users from channels (!)", VF_VENDOR | VF_COMMON);
+ return Version("Provides the UNINVITE command which lets users un-invite other users from channels", VF_VENDOR | VF_COMMON);
}
};
diff --git a/src/usermanager.cpp b/src/usermanager.cpp
index 6889ddba3..2d824c6b2 100644
--- a/src/usermanager.cpp
+++ b/src/usermanager.cpp
@@ -81,13 +81,7 @@ void UserManager::AddUser(int socket, ClientListenSocket* via, irc::sockets::soc
* First class check. We do this again in FullConnect after DNS is done, and NICK/USER is recieved.
* See my note down there for why this is required. DO NOT REMOVE. :) -- w00t
*/
- ConnectClass* i = New->SetClass();
-
- if (!i)
- {
- this->QuitUser(New, "Access denied by configuration");
- return;
- }
+ New->SetClass();
/*
* Check connect class settings and initialise settings into User.
diff --git a/src/users.cpp b/src/users.cpp
index dfb386871..bcf50a1ff 100644
--- a/src/users.cpp
+++ b/src/users.cpp
@@ -225,11 +225,9 @@ User::User(const std::string &uid)
{
server = ServerInstance->Config->ServerName;
age = ServerInstance->Time();
- Penalty = 0;
- lastping = signon = idle_lastmsg = nping = registered = 0;
+ signon = idle_lastmsg = registered = 0;
quietquit = quitting = exempt = dns_done = false;
fd = -1;
- AllowedPrivs = AllowedOperCommands = NULL;
uuid = uid;
client_sa.sa.sa_family = AF_UNSPEC;
@@ -244,8 +242,11 @@ User::User(const std::string &uid)
LocalUser::LocalUser() : User(ServerInstance->GetUID())
{
+ AllowedPrivs = AllowedOperCommands = NULL;
bytes_in = bytes_out = cmds_in = cmds_out = 0;
server_sa.sa.sa_family = AF_UNSPEC;
+ Penalty = 0;
+ lastping = nping = 0;
}
User::~User()
@@ -350,7 +351,7 @@ const std::string User::GetFullRealHost()
return this->cached_fullrealhost;
}
-bool User::IsInvited(const irc::string &channel)
+bool LocalUser::IsInvited(const irc::string &channel)
{
time_t now = ServerInstance->Time();
InvitedList::iterator safei;
@@ -372,7 +373,7 @@ bool User::IsInvited(const irc::string &channel)
return false;
}
-InvitedList* User::GetInviteList()
+InvitedList* LocalUser::GetInviteList()
{
time_t now = ServerInstance->Time();
/* Weed out expired invites here. */
@@ -390,7 +391,7 @@ InvitedList* User::GetInviteList()
return &invites;
}
-void User::InviteTo(const irc::string &channel, time_t invtimeout)
+void LocalUser::InviteTo(const irc::string &channel, time_t invtimeout)
{
time_t now = ServerInstance->Time();
if (invtimeout != 0 && now > invtimeout) return; /* Don't add invites that are expired from the get-go. */
@@ -409,7 +410,7 @@ void User::InviteTo(const irc::string &channel, time_t invtimeout)
invites.push_back(std::make_pair(channel, invtimeout));
}
-void User::RemoveInvite(const irc::string &channel)
+void LocalUser::RemoveInvite(const irc::string &channel)
{
for (InvitedList::iterator i = invites.begin(); i != invites.end(); i++)
{
@@ -421,11 +422,13 @@ void User::RemoveInvite(const irc::string &channel)
}
}
-bool User::HasModePermission(unsigned char mode, ModeType type)
+bool User::HasModePermission(unsigned char, ModeType)
{
- if (!IS_LOCAL(this))
- return true;
+ return true;
+}
+bool LocalUser::HasModePermission(unsigned char mode, ModeType type)
+{
if (!IS_OPER(this))
return false;
@@ -434,19 +437,20 @@ bool User::HasModePermission(unsigned char mode, ModeType type)
return ((type == MODETYPE_USER ? AllowedUserModes : AllowedChanModes))[(mode - 'A')];
}
-
-bool User::HasPermission(const std::string &command)
+/*
+ * users on remote servers can completely bypass all permissions based checks.
+ * This prevents desyncs when one server has different type/class tags to another.
+ * That having been said, this does open things up to the possibility of source changes
+ * allowing remote kills, etc - but if they have access to the src, they most likely have
+ * access to the conf - so it's an end to a means either way.
+ */
+bool User::HasPermission(const std::string&)
{
- /*
- * users on remote servers can completely bypass all permissions based checks.
- * This prevents desyncs when one server has different type/class tags to another.
- * That having been said, this does open things up to the possibility of source changes
- * allowing remote kills, etc - but if they have access to the src, they most likely have
- * access to the conf - so it's an end to a means either way.
- */
- if (!IS_LOCAL(this))
- return true;
+ return true;
+}
+bool LocalUser::HasPermission(const std::string &command)
+{
// are they even an oper at all?
if (!IS_OPER(this))
{
@@ -464,15 +468,13 @@ bool User::HasPermission(const std::string &command)
return false;
}
-
bool User::HasPrivPermission(const std::string &privstr, bool noisy)
{
- if (!IS_LOCAL(this))
- {
- ServerInstance->Logs->Log("PRIVS", DEBUG, "Remote (yes)");
- return true;
- }
+ return true;
+}
+bool LocalUser::HasPrivPermission(const std::string &privstr, bool noisy)
+{
if (!IS_OPER(this))
{
if (noisy)
@@ -510,14 +512,14 @@ void LocalUser::OnDataReady()
if (quitting)
return;
- if (MyClass && recvq.length() > MyClass->GetRecvqMax() && !HasPrivPermission("users/flood/increased-buffers"))
+ if (recvq.length() > MyClass->GetRecvqMax() && !HasPrivPermission("users/flood/increased-buffers"))
{
ServerInstance->Users->QuitUser(this, "RecvQ exceeded");
ServerInstance->SNO->WriteToSnoMask('a', "User %s RecvQ of %lu exceeds connect class maximum of %lu",
nick.c_str(), (unsigned long)recvq.length(), MyClass->GetRecvqMax());
}
unsigned long sendqmax = ULONG_MAX;
- if (MyClass && !HasPrivPermission("users/flood/increased-buffers"))
+ if (!HasPrivPermission("users/flood/increased-buffers"))
sendqmax = MyClass->GetSendqSoftMax();
int penaltymax = MyClass->GetPenaltyThreshold();
if (penaltymax == 0 || HasPrivPermission("users/flood/no-fakelag"))
@@ -566,7 +568,7 @@ eol_found:
void LocalUser::AddWriteBuf(const std::string &data)
{
- if (!quitting && MyClass && getSendQSize() + data.length() > MyClass->GetSendqHardMax() && !HasPrivPermission("users/flood/increased-buffers"))
+ if (!quitting && getSendQSize() + data.length() > MyClass->GetSendqHardMax() && !HasPrivPermission("users/flood/increased-buffers"))
{
/*
* Quit the user FIRST, because otherwise we could recurse
@@ -602,18 +604,6 @@ CullResult User::cull()
if (IS_LOCAL(this) && fd != INT_MAX)
Close();
- if (this->AllowedOperCommands)
- {
- delete AllowedOperCommands;
- AllowedOperCommands = NULL;
- }
-
- if (this->AllowedPrivs)
- {
- delete AllowedPrivs;
- AllowedPrivs = NULL;
- }
-
this->InvalidateCache();
this->DecrementModes();
@@ -630,6 +620,18 @@ CullResult LocalUser::cull()
else
ServerInstance->Logs->Log("USERS", DEBUG, "Failed to remove user from vector");
+ if (this->AllowedOperCommands)
+ {
+ delete AllowedOperCommands;
+ AllowedOperCommands = NULL;
+ }
+
+ if (this->AllowedPrivs)
+ {
+ delete AllowedPrivs;
+ AllowedPrivs = NULL;
+ }
+
if (client_sa.sa.sa_family != AF_UNSPEC)
ServerInstance->Users->RemoveCloneCounts(this);
return User::cull();
@@ -651,6 +653,14 @@ void User::Oper(const std::string &opertype, const std::string &opername)
this->oper.assign(opertype, 0, 512);
ServerInstance->Users->all_opers.push_back(this);
+ if (IS_LOCAL(this))
+ IS_LOCAL(this)->OperInternal();
+
+ FOREACH_MOD(I_OnPostOper,OnPostOper(this, opertype, opername));
+}
+
+void LocalUser::OperInternal()
+{
/*
* This might look like it's in the wrong place.
* It is *not*!
@@ -721,60 +731,64 @@ void User::Oper(const std::string &opertype, const std::string &opername)
}
}
}
-
- FOREACH_MOD(I_OnPostOper,OnPostOper(this, opertype, opername));
}
void User::UnOper()
{
- if (IS_OPER(this))
- {
- /*
- * unset their oper type (what IS_OPER checks).
- * note, order is important - this must come before modes as -o attempts
- * to call UnOper. -- w00t
- */
- this->oper.clear();
+ if (!IS_OPER(this))
+ return;
+ /*
+ * unset their oper type (what IS_OPER checks).
+ * note, order is important - this must come before modes as -o attempts
+ * to call UnOper. -- w00t
+ */
+ this->oper.clear();
- /* Remove all oper only modes from the user when the deoper - Bug #466*/
- std::string moderemove("-");
- for (unsigned char letter = 'A'; letter <= 'z'; letter++)
- {
- ModeHandler* mh = ServerInstance->Modes->FindMode(letter, MODETYPE_USER);
- if (mh && mh->NeedsOper())
- moderemove += letter;
- }
+ /* Remove all oper only modes from the user when the deoper - Bug #466*/
+ std::string moderemove("-");
+ for (unsigned char letter = 'A'; letter <= 'z'; letter++)
+ {
+ ModeHandler* mh = ServerInstance->Modes->FindMode(letter, MODETYPE_USER);
+ if (mh && mh->NeedsOper())
+ moderemove += letter;
+ }
- std::vector<std::string> parameters;
- parameters.push_back(this->nick);
- parameters.push_back(moderemove);
- ServerInstance->Parser->CallHandler("MODE", parameters, this);
+ std::vector<std::string> parameters;
+ parameters.push_back(this->nick);
+ parameters.push_back(moderemove);
- /* remove the user from the oper list. Will remove multiple entries as a safeguard against bug #404 */
- ServerInstance->Users->all_opers.remove(this);
+ ServerInstance->Parser->CallHandler("MODE", parameters, this);
- if (AllowedOperCommands)
- {
- delete AllowedOperCommands;
- AllowedOperCommands = NULL;
- }
+ /* remove the user from the oper list. Will remove multiple entries as a safeguard against bug #404 */
+ ServerInstance->Users->all_opers.remove(this);
- if (AllowedPrivs)
- {
- delete AllowedPrivs;
- AllowedPrivs = NULL;
- }
+ if (IS_LOCAL(this))
+ IS_LOCAL(this)->UnOperInternal();
+ this->modes[UM_OPERATOR] = 0;
+}
- AllowedUserModes.reset();
- AllowedChanModes.reset();
- this->modes[UM_OPERATOR] = 0;
+void LocalUser::UnOperInternal()
+{
+ if (AllowedOperCommands)
+ {
+ delete AllowedOperCommands;
+ AllowedOperCommands = NULL;
+ }
+
+ if (AllowedPrivs)
+ {
+ delete AllowedPrivs;
+ AllowedPrivs = NULL;
}
+ AllowedUserModes.reset();
+ AllowedChanModes.reset();
}
+
/* adds or updates an entry in the whowas list */
void User::AddToWhoWas()
{
@@ -790,11 +804,15 @@ void User::AddToWhoWas()
/*
* Check class restrictions
*/
-void User::CheckClass()
+void LocalUser::CheckClass()
{
ConnectClass* a = this->MyClass;
- if ((!a) || (a->type == CC_DENY))
+ if (!a)
+ {
+ ServerInstance->Users->QuitUser(this, "Access denied by configuration");
+ }
+ else if (a->type == CC_DENY)
{
ServerInstance->Users->QuitUser(this, "Unauthorised connection");
return;
@@ -852,7 +870,7 @@ void LocalUser::FullConnect()
/* Check the password, if one is required by the user's connect class.
* This CANNOT be in CheckClass(), because that is called prior to PASS as well!
*/
- if (MyClass && !MyClass->pass.empty())
+ if (!MyClass->pass.empty())
{
if (ServerInstance->PassCompare(this, MyClass->pass.c_str(), password.c_str(), MyClass->hash.c_str()))
{
@@ -1641,7 +1659,7 @@ void User::SplitChanList(User* dest, const std::string &cl)
* then their ip will be taken as 'priority' anyway, so for example,
* <connect allow="127.0.0.1"> will match joe!bloggs@localhost
*/
-ConnectClass* LocalUser::SetClass(const std::string &explicit_name)
+void LocalUser::SetClass(const std::string &explicit_name)
{
ConnectClass *found = NULL;
@@ -1719,8 +1737,6 @@ ConnectClass* LocalUser::SetClass(const std::string &explicit_name)
{
MyClass = found;
}
-
- return this->MyClass;
}
/* looks up a users password for their connection class (<ALLOW>/<DENY> tags)
@@ -1728,9 +1744,14 @@ ConnectClass* LocalUser::SetClass(const std::string &explicit_name)
* then their ip will be taken as 'priority' anyway, so for example,
* <connect allow="127.0.0.1"> will match joe!bloggs@localhost
*/
+ConnectClass* LocalUser::GetClass()
+{
+ return MyClass;
+}
+
ConnectClass* User::GetClass()
{
- return this->MyClass;
+ return NULL;
}
void User::PurgeEmptyChannels()
@@ -1776,11 +1797,6 @@ void User::ShowRULES()
this->WriteNumeric(RPL_RULESEND, "%s :End of RULES command.",this->nick.c_str());
}
-void User::IncreasePenalty(int increase)
-{
- this->Penalty += increase;
-}
-
void FakeUser::SetFakeServer(std::string name)
{
this->nick = name;