mirror of
https://github.com/anope/anope.git
synced 2026-06-12 18:54:47 +02:00
Remove the asynchronous identifing hack and replace it with something better. Fixes m_*_authentication only being able to properly work when people identify normally using nickserv/identify
This commit is contained in:
@@ -359,6 +359,9 @@ m_sql_authentication
|
||||
* @n@ is replaced with the user's nickname
|
||||
* @i@ is replaced with the user's IP
|
||||
*
|
||||
* Note that @n@ and @i@ may not always exist in the case of a user identifying outside of the normal
|
||||
* nickserv/identify command, such as through the web panel.
|
||||
*
|
||||
* Furthermore, if a field named email is returned from this query the user's email is
|
||||
* set to its value.
|
||||
*/
|
||||
|
||||
@@ -304,7 +304,39 @@ class CoreExport NickCore : public Extensible, public Flags<NickCoreFlag, NI_END
|
||||
* Deletes all the memory allocated in the certificate list vector and then clears the vector.
|
||||
*/
|
||||
void ClearCert();
|
||||
};
|
||||
|
||||
class IdentifyRequest
|
||||
{
|
||||
Anope::string account;
|
||||
Anope::string password;
|
||||
|
||||
std::set<Module *> holds;
|
||||
bool dispatched;
|
||||
bool success;
|
||||
|
||||
static std::set<IdentifyRequest *> requests;
|
||||
|
||||
protected:
|
||||
IdentifyRequest(const Anope::string &acc, const Anope::string &pass);
|
||||
virtual ~IdentifyRequest();
|
||||
|
||||
public:
|
||||
virtual void OnSuccess() = 0;
|
||||
virtual void OnFail() = 0;
|
||||
|
||||
const Anope::string &GetAccount() const { return account; }
|
||||
const Anope::string &GetPassword() const { return password; }
|
||||
|
||||
/* Hold this request. Once held it must be Release()d later on */
|
||||
void Hold(Module *m);
|
||||
void Release(Module *m);
|
||||
|
||||
void Success(Module *m);
|
||||
|
||||
void Dispatch();
|
||||
|
||||
static void ModuleUnload(Module *m);
|
||||
};
|
||||
|
||||
extern CoreExport void change_core_display(NickCore *nc);
|
||||
|
||||
@@ -26,6 +26,7 @@ class ConnectionSocket;
|
||||
class DNSPacket;
|
||||
class dynamic_reference_base;
|
||||
class Entry;
|
||||
class IdentifyRequest;
|
||||
class InfoFormatter;
|
||||
class ListenSocket;
|
||||
class Log;
|
||||
|
||||
+4
-8
@@ -765,15 +765,11 @@ class CoreExport Module : public Extensible
|
||||
*/
|
||||
virtual void OnNickInfo(CommandSource &source, NickAlias *na, InfoFormatter &info, bool ShowHidden) { }
|
||||
|
||||
/** Check whether a users password is correct.
|
||||
* @param u The user
|
||||
* @param command The command the user is doing
|
||||
* @param params Command params
|
||||
* @param account The account the password should be checked against
|
||||
* @param password The password
|
||||
* @return EVENT_ALLOW to allow the password, EVENT_STOP to stop processing completely
|
||||
/** Check whether a username and password is correct
|
||||
* @param u The user trying to identify, if applicable.
|
||||
* @param req The login request
|
||||
*/
|
||||
virtual EventReturn OnCheckAuthentication(Command *c, CommandSource *source, const std::vector<Anope::string> ¶ms, const Anope::string &account, const Anope::string &password) { return EVENT_CONTINUE; }
|
||||
virtual void OnCheckAuthentication(User *u, IdentifyRequest *req) { }
|
||||
|
||||
/** Called when a user does /ns update
|
||||
* @param u The user
|
||||
|
||||
@@ -13,6 +13,43 @@
|
||||
|
||||
#include "module.h"
|
||||
|
||||
class NSGhostRequest : public IdentifyRequest
|
||||
{
|
||||
CommandSource source;
|
||||
Command *cmd;
|
||||
|
||||
public:
|
||||
NSGhostRequest(CommandSource &src, Command *c, const Anope::string &user, const Anope::string &pass) : IdentifyRequest(user, pass), source(src), cmd(c) { }
|
||||
|
||||
void OnSuccess() anope_override
|
||||
{
|
||||
if (!source.GetUser() || !source.service)
|
||||
return;
|
||||
|
||||
User *user = source.GetUser();
|
||||
if (!user->IsIdentified())
|
||||
source.Reply(_("You may not ghost an unidentified user, use RECOVER instead."));
|
||||
else
|
||||
{
|
||||
Log(LOG_COMMAND, source, cmd) << "for " << GetAccount();
|
||||
Anope::string buf = "GHOST command used by " + source.GetNick();
|
||||
user->Kill(source.service->nick, buf);
|
||||
source.Reply(_("Ghost with your nick has been killed."));
|
||||
}
|
||||
}
|
||||
|
||||
void OnFail() anope_override
|
||||
{
|
||||
source.Reply(ACCESS_DENIED);
|
||||
if (!GetPassword().empty())
|
||||
{
|
||||
Log(LOG_COMMAND, source, cmd) << "with an invalid password for " << GetAccount();
|
||||
if (source.GetUser())
|
||||
bad_password(source.GetUser());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class CommandNSGhost : public Command
|
||||
{
|
||||
public:
|
||||
@@ -50,37 +87,21 @@ class CommandNSGhost : public Command
|
||||
ok = true;
|
||||
else if (source.GetUser() && !source.GetUser()->fingerprint.empty() && na->nc->FindCert(source.GetUser()->fingerprint))
|
||||
ok = true;
|
||||
else if (!pass.empty())
|
||||
{
|
||||
EventReturn MOD_RESULT;
|
||||
FOREACH_RESULT(I_OnCheckAuthentication, OnCheckAuthentication(this, &source, params, na->nc->display, pass));
|
||||
if (MOD_RESULT == EVENT_STOP)
|
||||
return;
|
||||
else if (MOD_RESULT == EVENT_ALLOW)
|
||||
ok = true;
|
||||
}
|
||||
|
||||
if (ok)
|
||||
if (ok == false && !pass.empty())
|
||||
{
|
||||
if (!user->IsIdentified())
|
||||
source.Reply(_("You may not ghost an unidentified user, use RECOVER instead."));
|
||||
else
|
||||
{
|
||||
Log(LOG_COMMAND, source, this) << "for " << nick;
|
||||
Anope::string buf = "GHOST command used by " + source.GetNick();
|
||||
user->Kill(Config->NickServ, buf);
|
||||
source.Reply(_("Ghost with your nick has been killed."), nick.c_str());
|
||||
}
|
||||
NSGhostRequest *req = new NSGhostRequest(source, this, na->nc->display, pass);
|
||||
FOREACH_MOD(I_OnCheckAuthentication, OnCheckAuthentication(source.GetUser(), req));
|
||||
req->Dispatch();
|
||||
}
|
||||
else
|
||||
{
|
||||
source.Reply(ACCESS_DENIED);
|
||||
if (!pass.empty())
|
||||
{
|
||||
Log(LOG_COMMAND, source, this) << "with an invalid password for " << nick;
|
||||
if (source.GetUser())
|
||||
bad_password(source.GetUser());
|
||||
}
|
||||
NSGhostRequest req(source, this, na->nc->display, pass);
|
||||
|
||||
if (ok)
|
||||
req.OnSuccess();
|
||||
else
|
||||
req.OnFail();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,61 @@
|
||||
|
||||
#include "module.h"
|
||||
|
||||
class NSGroupRequest : public IdentifyRequest
|
||||
{
|
||||
CommandSource source;
|
||||
Command *cmd;
|
||||
Anope::string nick;
|
||||
dynamic_reference<NickAlias> target;
|
||||
|
||||
public:
|
||||
NSGroupRequest(CommandSource &src, Command *c, const Anope::string &n, NickAlias *targ, const Anope::string &pass) : IdentifyRequest(targ->nc->display, pass), source(src), cmd(c), nick(n), target(targ) { }
|
||||
|
||||
void OnSuccess() anope_override
|
||||
{
|
||||
if (!source.GetUser() || source.GetUser()->nick != nick || !target || !target->nc)
|
||||
return;
|
||||
|
||||
User *u = source.GetUser();
|
||||
NickAlias *na = findnick(nick);
|
||||
/* If the nick is already registered, drop it. */
|
||||
if (na)
|
||||
{
|
||||
FOREACH_MOD(I_OnChangeCoreDisplay, OnChangeCoreDisplay(na->nc, u->nick));
|
||||
na->destroy();
|
||||
}
|
||||
|
||||
na = new NickAlias(nick, target->nc);
|
||||
|
||||
Anope::string last_usermask = u->GetIdent() + "@" + u->GetDisplayedHost();
|
||||
na->last_usermask = last_usermask;
|
||||
na->last_realname = u->realname;
|
||||
na->time_registered = na->last_seen = Anope::CurTime;
|
||||
|
||||
u->Login(target->nc);
|
||||
ircdproto->SendLogin(u);
|
||||
if (!Config->NoNicknameOwnership && na->nc == u->Account() && na->nc->HasFlag(NI_UNCONFIRMED) == false)
|
||||
u->SetMode(findbot(Config->NickServ), UMODE_REGISTERED);
|
||||
FOREACH_MOD(I_OnNickGroup, OnNickGroup(u, target));
|
||||
|
||||
Log(LOG_COMMAND, source, cmd) << "makes " << nick << " join group of " << target->nick << " (" << target->nc->display << ") (email: " << (!target->nc->email.empty() ? target->nc->email : "none") << ")";
|
||||
source.Reply(_("You are now in the group of \002%s\002."), target->nick.c_str());
|
||||
|
||||
u->lastnickreg = Anope::CurTime;
|
||||
|
||||
}
|
||||
|
||||
void OnFail() anope_override
|
||||
{
|
||||
if (!source.GetUser())
|
||||
return;
|
||||
|
||||
Log(LOG_COMMAND, source, cmd) << "failed group for " << target->nick;
|
||||
source.Reply(PASSWORD_INCORRECT);
|
||||
bad_password(source.GetUser());
|
||||
}
|
||||
};
|
||||
|
||||
class CommandNSGroup : public Command
|
||||
{
|
||||
public:
|
||||
@@ -62,7 +117,7 @@ class CommandNSGroup : public Command
|
||||
source.Reply(NICK_X_NOT_REGISTERED, nick.c_str());
|
||||
else if (Anope::CurTime < u->lastnickreg + Config->NSRegDelay)
|
||||
source.Reply(_("Please wait %d seconds before using the GROUP command again."), (Config->NSRegDelay + u->lastnickreg) - Anope::CurTime);
|
||||
else if (target && target->nc->HasFlag(NI_SUSPENDED))
|
||||
else if (target->nc->HasFlag(NI_SUSPENDED))
|
||||
{
|
||||
Log(LOG_COMMAND, source, this) << "tried to use GROUP for SUSPENDED nick " << target->nick;
|
||||
source.Reply(NICK_X_SUSPENDED, target->nick.c_str());
|
||||
@@ -75,6 +130,12 @@ class CommandNSGroup : public Command
|
||||
source.Reply(_("Your nick is already registered."));
|
||||
else if (Config->NSMaxAliases && (target->nc->aliases.size() >= Config->NSMaxAliases) && !target->nc->IsServicesOper())
|
||||
source.Reply(_("There are too many nicks in %s's group."));
|
||||
else if (u->nick.length() <= Config->NSGuestNickPrefix.length() + 7 &&
|
||||
u->nick.length() >= Config->NSGuestNickPrefix.length() + 1 &&
|
||||
!u->nick.find_ci(Config->NSGuestNickPrefix) && !u->nick.substr(Config->NSGuestNickPrefix.length()).find_first_not_of("1234567890"))
|
||||
{
|
||||
source.Reply(NICK_CANNOT_BE_REGISTERED, u->nick.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
bool ok = false;
|
||||
@@ -82,63 +143,23 @@ class CommandNSGroup : public Command
|
||||
ok = true;
|
||||
else if (!u->fingerprint.empty() && target->nc->FindCert(u->fingerprint))
|
||||
ok = true;
|
||||
else if (!pass.empty())
|
||||
|
||||
if (ok == false && !pass.empty())
|
||||
{
|
||||
EventReturn MOD_RESULT;
|
||||
FOREACH_RESULT(I_OnCheckAuthentication, OnCheckAuthentication(this, &source, params, target->nc->display, pass));
|
||||
if (MOD_RESULT == EVENT_STOP)
|
||||
return;
|
||||
else if (MOD_RESULT == EVENT_ALLOW)
|
||||
ok = true;
|
||||
}
|
||||
if (ok)
|
||||
{
|
||||
/* If the nick is already registered, drop it.
|
||||
* If not, check that it is valid.
|
||||
*/
|
||||
if (na)
|
||||
{
|
||||
FOREACH_MOD(I_OnChangeCoreDisplay, OnChangeCoreDisplay(na->nc, u->nick));
|
||||
na->destroy();
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t prefixlen = Config->NSGuestNickPrefix.length();
|
||||
size_t nicklen = u->nick.length();
|
||||
|
||||
if (nicklen <= prefixlen + 7 && nicklen >= prefixlen + 1 && !u->nick.find_ci(Config->NSGuestNickPrefix) && !u->nick.substr(prefixlen).find_first_not_of("1234567890"))
|
||||
{
|
||||
source.Reply(NICK_CANNOT_BE_REGISTERED, u->nick.c_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
na = new NickAlias(u->nick, target->nc);
|
||||
|
||||
Anope::string last_usermask = u->GetIdent() + "@" + u->GetDisplayedHost();
|
||||
na->last_usermask = last_usermask;
|
||||
na->last_realname = u->realname;
|
||||
na->time_registered = na->last_seen = Anope::CurTime;
|
||||
|
||||
u->Login(target->nc);
|
||||
ircdproto->SendLogin(u);
|
||||
if (!Config->NoNicknameOwnership && na->nc == u->Account() && na->nc->HasFlag(NI_UNCONFIRMED) == false)
|
||||
u->SetMode(findbot(Config->NickServ), UMODE_REGISTERED);
|
||||
FOREACH_MOD(I_OnNickGroup, OnNickGroup(u, target));
|
||||
|
||||
Log(LOG_COMMAND, source, this) << "makes " << u->nick << " join group of " << target->nick << " (" << target->nc->display << ") (email: " << (!target->nc->email.empty() ? target->nc->email : "none") << ")";
|
||||
source.Reply(_("You are now in the group of \002%s\002."), target->nick.c_str());
|
||||
|
||||
u->lastnickreg = Anope::CurTime;
|
||||
NSGroupRequest *req = new NSGroupRequest(source, this, u->nick, target, pass);
|
||||
FOREACH_MOD(I_OnCheckAuthentication, OnCheckAuthentication(source.GetUser(), req));
|
||||
req->Dispatch();
|
||||
}
|
||||
else
|
||||
{
|
||||
Log(LOG_COMMAND, source, this) << "failed group for " << target->nick;
|
||||
source.Reply(PASSWORD_INCORRECT);
|
||||
bad_password(u);
|
||||
NSGroupRequest req(source, this, u->nick, target, pass);
|
||||
|
||||
if (ok)
|
||||
req.OnSuccess();
|
||||
else
|
||||
req.OnFail();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
|
||||
|
||||
@@ -13,6 +13,47 @@
|
||||
|
||||
#include "module.h"
|
||||
|
||||
class NSIdentifyRequest : public IdentifyRequest
|
||||
{
|
||||
CommandSource source;
|
||||
Command *cmd;
|
||||
|
||||
public:
|
||||
NSIdentifyRequest(CommandSource &s, Command *c, const Anope::string &acc, const Anope::string &pass) : IdentifyRequest(acc, pass), source(s), cmd(c) { }
|
||||
|
||||
void OnSuccess() anope_override
|
||||
{
|
||||
if (!source.GetUser())
|
||||
return;
|
||||
|
||||
User *u = source.GetUser();
|
||||
NickAlias *na = findnick(GetAccount());
|
||||
|
||||
if (!na)
|
||||
source.Reply(NICK_X_NOT_REGISTERED, GetAccount().c_str());
|
||||
else
|
||||
{
|
||||
if (u->IsIdentified())
|
||||
Log(LOG_COMMAND, source, cmd) << "to log out of account " << u->Account()->display;
|
||||
|
||||
Log(LOG_COMMAND, source, cmd) << "and identified for account " << na->nc->display;
|
||||
source.Reply(_("Password accepted - you are now recognized."));
|
||||
u->Identify(na);
|
||||
na->Release();
|
||||
}
|
||||
}
|
||||
|
||||
void OnFail() anope_override
|
||||
{
|
||||
if (source.GetUser())
|
||||
{
|
||||
Log(LOG_COMMAND, source, cmd) << "and failed to identify";
|
||||
source.Reply(PASSWORD_INCORRECT);
|
||||
bad_password(source.GetUser());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class CommandNSIdentify : public Command
|
||||
{
|
||||
public:
|
||||
@@ -40,29 +81,9 @@ class CommandNSIdentify : public Command
|
||||
source.Reply(_("You are already identified."));
|
||||
else
|
||||
{
|
||||
EventReturn MOD_RESULT;
|
||||
FOREACH_RESULT(I_OnCheckAuthentication, OnCheckAuthentication(this, &source, params, na ? na->nc->display : nick, pass));
|
||||
if (MOD_RESULT == EVENT_STOP)
|
||||
return;
|
||||
|
||||
if (!na)
|
||||
source.Reply(NICK_X_NOT_REGISTERED, nick.c_str());
|
||||
else if (MOD_RESULT != EVENT_ALLOW)
|
||||
{
|
||||
Log(LOG_COMMAND, source, this) << "and failed to identify";
|
||||
source.Reply(PASSWORD_INCORRECT);
|
||||
bad_password(u);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (u->IsIdentified())
|
||||
Log(LOG_COMMAND, source, this) << "to log out of account " << u->Account()->display;
|
||||
|
||||
Log(LOG_COMMAND, source, this) << "and identified for account " << na->nc->display;
|
||||
source.Reply(_("Password accepted - you are now recognized."));
|
||||
u->Identify(na);
|
||||
na->Release();
|
||||
}
|
||||
NSIdentifyRequest *req = new NSIdentifyRequest(source, this, na ? na->nc->display : nick, pass);
|
||||
FOREACH_MOD(I_OnCheckAuthentication, OnCheckAuthentication(source.GetUser(), req));
|
||||
req->Dispatch();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -14,11 +14,22 @@
|
||||
|
||||
#include "module.h"
|
||||
|
||||
class CommandNSRecover : public Command
|
||||
class NSRecoverRequest : public IdentifyRequest
|
||||
{
|
||||
private:
|
||||
void DoRecover(CommandSource &source, User *u, NickAlias *na, const Anope::string &nick)
|
||||
CommandSource source;
|
||||
Command *cmd;
|
||||
dynamic_reference<NickAlias> na;
|
||||
|
||||
public:
|
||||
NSRecoverRequest(CommandSource &src, Command *c, NickAlias *n, const Anope::string &pass) : IdentifyRequest(n->nc->display, pass), source(src), cmd(c), na(n) { }
|
||||
|
||||
void OnSuccess() anope_override
|
||||
{
|
||||
if (!source.GetUser() || !na)
|
||||
return;
|
||||
|
||||
User *u = source.GetUser();
|
||||
|
||||
u->SendMessage(source.owner, FORCENICKCHANGE_NOW);
|
||||
|
||||
if (u->Account() == na->nc)
|
||||
@@ -31,9 +42,27 @@ class CommandNSRecover : public Command
|
||||
|
||||
/* Convert Config->NSReleaseTimeout seconds to string format */
|
||||
Anope::string relstr = duration(Config->NSReleaseTimeout);
|
||||
source.Reply(NICK_RECOVERED, Config->UseStrictPrivMsgString.c_str(), Config->NickServ.c_str(), nick.c_str(), relstr.c_str());
|
||||
source.Reply(NICK_RECOVERED, Config->UseStrictPrivMsgString.c_str(), Config->NickServ.c_str(), na->nick.c_str(), relstr.c_str());
|
||||
}
|
||||
|
||||
void OnFail() anope_override
|
||||
{
|
||||
if (!source.GetUser())
|
||||
return;
|
||||
|
||||
User *u = source.GetUser();
|
||||
|
||||
source.Reply(ACCESS_DENIED);
|
||||
if (!GetPassword().empty())
|
||||
{
|
||||
Log(LOG_COMMAND, source, cmd) << "with invalid password for " << na->nick;
|
||||
bad_password(u);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class CommandNSRecover : public Command
|
||||
{
|
||||
public:
|
||||
CommandNSRecover(Module *creator) : Command(creator, "nickserv/recover", 1, 2)
|
||||
{
|
||||
@@ -60,25 +89,6 @@ class CommandNSRecover : public Command
|
||||
source.Reply(NICK_X_SUSPENDED, na->nick.c_str());
|
||||
else if (nick.equals_ci(source.GetNick()))
|
||||
source.Reply(_("You can't recover yourself!"));
|
||||
else if (!pass.empty())
|
||||
{
|
||||
EventReturn MOD_RESULT;
|
||||
FOREACH_RESULT(I_OnCheckAuthentication, OnCheckAuthentication(this, &source, params, na->nc->display, pass));
|
||||
if (MOD_RESULT == EVENT_STOP)
|
||||
return;
|
||||
|
||||
if (MOD_RESULT == EVENT_ALLOW)
|
||||
{
|
||||
this->DoRecover(source, u2, na, nick);
|
||||
}
|
||||
else
|
||||
{
|
||||
source.Reply(ACCESS_DENIED);
|
||||
Log(LOG_COMMAND, source, this) << "with invalid password for " << nick;
|
||||
if (source.GetUser())
|
||||
bad_password(source.GetUser());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bool ok = false;
|
||||
@@ -88,12 +98,23 @@ class CommandNSRecover : public Command
|
||||
ok = true;
|
||||
else if (source.GetUser() && !source.GetUser()->fingerprint.empty() && na->nc->FindCert(source.GetUser()->fingerprint))
|
||||
ok = true;
|
||||
if (ok)
|
||||
this->DoRecover(source, u2, na, nick);
|
||||
|
||||
if (ok == false && !pass.empty())
|
||||
{
|
||||
NSRecoverRequest *req = new NSRecoverRequest(source, this, na, pass);
|
||||
FOREACH_MOD(I_OnCheckAuthentication, OnCheckAuthentication(source.GetUser(), req));
|
||||
req->Dispatch();
|
||||
}
|
||||
else
|
||||
source.Reply(ACCESS_DENIED);
|
||||
{
|
||||
NSRecoverRequest req(source, this, na, pass);
|
||||
|
||||
if (ok)
|
||||
req.OnSuccess();
|
||||
else
|
||||
req.OnFail();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
|
||||
|
||||
@@ -13,6 +13,38 @@
|
||||
|
||||
#include "module.h"
|
||||
|
||||
class NSReleaseRequest : public IdentifyRequest
|
||||
{
|
||||
CommandSource source;
|
||||
Command *cmd;
|
||||
dynamic_reference<NickAlias> na;
|
||||
|
||||
public:
|
||||
NSReleaseRequest(CommandSource &src, Command *c, NickAlias *n, const Anope::string &pass) : IdentifyRequest(n->nc->display, pass), source(src), cmd(c), na(n) { }
|
||||
|
||||
void OnSuccess() anope_override
|
||||
{
|
||||
if (!source.GetUser() || !na)
|
||||
return;
|
||||
|
||||
bool override = source.GetAccount() != na->nc && source.HasPriv("nickserv/release");
|
||||
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, cmd) << "for nickname " << na->nick;
|
||||
na->Release();
|
||||
source.Reply(_("Services' hold on \002%s\002 has been released."), na->nick.c_str());
|
||||
}
|
||||
|
||||
void OnFail() anope_override
|
||||
{
|
||||
source.Reply(ACCESS_DENIED);
|
||||
if (!GetPassword().empty())
|
||||
{
|
||||
Log(LOG_COMMAND, source, cmd) << "with invalid password for " << na->nick;
|
||||
if (!source.GetUser())
|
||||
bad_password(source.GetUser());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class CommandNSRelease : public Command
|
||||
{
|
||||
public:
|
||||
@@ -35,27 +67,6 @@ class CommandNSRelease : public Command
|
||||
source.Reply(NICK_X_SUSPENDED, na->nick.c_str());
|
||||
else if (!na->HasFlag(NS_HELD))
|
||||
source.Reply(_("Nick \002%s\002 isn't being held."), nick.c_str());
|
||||
else if (!pass.empty())
|
||||
{
|
||||
EventReturn MOD_RESULT;
|
||||
FOREACH_RESULT(I_OnCheckAuthentication, OnCheckAuthentication(this, &source, params, na->nc->display, pass));
|
||||
if (MOD_RESULT == EVENT_STOP)
|
||||
return;
|
||||
|
||||
if (MOD_RESULT == EVENT_ALLOW)
|
||||
{
|
||||
Log(LOG_COMMAND, source, this) << "for nickname " << na->nick;
|
||||
na->Release();
|
||||
source.Reply(_("Services' hold on \002%s\002 has been released."), nick.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
source.Reply(ACCESS_DENIED);
|
||||
Log(LOG_COMMAND, source, this) << "invalid password for " << nick;
|
||||
if (source.GetUser())
|
||||
bad_password(source.GetUser());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bool override = source.GetAccount() != na->nc && source.HasPriv("nickserv/release");
|
||||
@@ -67,14 +78,22 @@ class CommandNSRelease : public Command
|
||||
ok = true;
|
||||
else if (source.GetUser() && !source.GetUser()->fingerprint.empty() && na->nc->FindCert(source.GetUser()->fingerprint))
|
||||
ok = true;
|
||||
if (ok)
|
||||
|
||||
if (ok == false && !pass.empty())
|
||||
{
|
||||
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this) << "for nickname " << na->nick;
|
||||
na->Release();
|
||||
source.Reply(_("Services' hold on \002%s\002 has been released."), nick.c_str());
|
||||
NSReleaseRequest *req = new NSReleaseRequest(source, this, na, pass);
|
||||
FOREACH_MOD(I_OnCheckAuthentication, OnCheckAuthentication(source.GetUser(), req));
|
||||
req->Dispatch();
|
||||
}
|
||||
else
|
||||
source.Reply(ACCESS_DENIED);
|
||||
{
|
||||
NSReleaseRequest req(source, this, na, pass);
|
||||
|
||||
if (ok)
|
||||
req.OnSuccess();
|
||||
else
|
||||
req.OnFail();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -339,33 +339,31 @@ class EMD5 : public Module
|
||||
return EVENT_ALLOW;
|
||||
}
|
||||
|
||||
EventReturn OnCheckAuthentication(Command *c, CommandSource *source, const std::vector<Anope::string> ¶ms, const Anope::string &account, const Anope::string &password) anope_override
|
||||
void OnCheckAuthentication(User *, IdentifyRequest *req) anope_override
|
||||
{
|
||||
const NickAlias *na = findnick(account);
|
||||
const NickAlias *na = findnick(req->GetAccount());
|
||||
if (na == NULL)
|
||||
return EVENT_CONTINUE;
|
||||
return;
|
||||
NickCore *nc = na->nc;
|
||||
|
||||
size_t pos = nc->pass.find(':');
|
||||
if (pos == Anope::string::npos)
|
||||
return EVENT_CONTINUE;
|
||||
return;
|
||||
Anope::string hash_method(nc->pass.begin(), nc->pass.begin() + pos);
|
||||
if (!hash_method.equals_cs("md5"))
|
||||
return EVENT_CONTINUE;
|
||||
return;
|
||||
|
||||
Anope::string buf;
|
||||
this->OnEncrypt(password, buf);
|
||||
this->OnEncrypt(req->GetPassword(), buf);
|
||||
if (nc->pass.equals_cs(buf))
|
||||
{
|
||||
/* if we are NOT the first module in the list,
|
||||
* we want to re-encrypt the pass with the new encryption
|
||||
*/
|
||||
if (ModuleManager::FindFirstOf(ENCRYPTION) != this)
|
||||
enc_encrypt(password, nc->pass);
|
||||
return EVENT_ALLOW;
|
||||
enc_encrypt(req->GetPassword(), nc->pass);
|
||||
req->Success(this);
|
||||
}
|
||||
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -41,33 +41,31 @@ class ENone : public Module
|
||||
return EVENT_ALLOW;
|
||||
}
|
||||
|
||||
EventReturn OnCheckAuthentication(Command *c, CommandSource *source, const std::vector<Anope::string> ¶ms, const Anope::string &account, const Anope::string &password) anope_override
|
||||
void OnCheckAuthentication(User *, IdentifyRequest *req) anope_override
|
||||
{
|
||||
const NickAlias *na = findnick(account);
|
||||
const NickAlias *na = findnick(req->GetAccount());
|
||||
if (na == NULL)
|
||||
return EVENT_CONTINUE;
|
||||
return;
|
||||
NickCore *nc = na->nc;
|
||||
|
||||
size_t pos = nc->pass.find(':');
|
||||
if (pos == Anope::string::npos)
|
||||
return EVENT_CONTINUE;
|
||||
return;
|
||||
Anope::string hash_method(nc->pass.begin(), nc->pass.begin() + pos);
|
||||
if (!hash_method.equals_cs("plain"))
|
||||
return EVENT_CONTINUE;
|
||||
return;
|
||||
|
||||
Anope::string buf;
|
||||
this->OnEncrypt(password, buf);
|
||||
this->OnEncrypt(req->GetPassword(), buf);
|
||||
if (nc->pass.equals_cs(buf))
|
||||
{
|
||||
/* if we are NOT the first module in the list,
|
||||
* we want to re-encrypt the pass with the new encryption
|
||||
*/
|
||||
if (ModuleManager::FindFirstOf(ENCRYPTION) != this)
|
||||
enc_encrypt(password, nc->pass);
|
||||
return EVENT_ALLOW;
|
||||
enc_encrypt(req->GetPassword(), nc->pass);
|
||||
req->Success(this);
|
||||
}
|
||||
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -349,33 +349,31 @@ class EOld : public Module
|
||||
return EVENT_ALLOW;
|
||||
}
|
||||
|
||||
EventReturn OnCheckAuthentication(Command *c, CommandSource *source, const std::vector<Anope::string> ¶ms, const Anope::string &account, const Anope::string &password) anope_override
|
||||
void OnCheckAuthentication(User *, IdentifyRequest *req) anope_override
|
||||
{
|
||||
const NickAlias *na = findnick(account);
|
||||
const NickAlias *na = findnick(req->GetAccount());
|
||||
if (na == NULL)
|
||||
return EVENT_CONTINUE;
|
||||
return;
|
||||
NickCore *nc = na->nc;
|
||||
|
||||
size_t pos = nc->pass.find(':');
|
||||
if (pos == Anope::string::npos)
|
||||
return EVENT_CONTINUE;
|
||||
return;
|
||||
Anope::string hash_method(nc->pass.begin(), nc->pass.begin() + pos);
|
||||
if (!hash_method.equals_cs("oldmd5"))
|
||||
return EVENT_CONTINUE;
|
||||
return;
|
||||
|
||||
Anope::string buf;
|
||||
this->OnEncrypt(password, buf);
|
||||
this->OnEncrypt(req->GetPassword(), buf);
|
||||
if (nc->pass.equals_cs(buf))
|
||||
{
|
||||
/* if we are NOT the first module in the list,
|
||||
* we want to re-encrypt the pass with the new encryption
|
||||
*/
|
||||
if (ModuleManager::FindFirstOf(ENCRYPTION) != this)
|
||||
enc_encrypt(password, nc->pass);
|
||||
return EVENT_ALLOW;
|
||||
enc_encrypt(req->GetPassword(), nc->pass);
|
||||
req->Success(this);
|
||||
}
|
||||
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -192,30 +192,28 @@ class ESHA1 : public Module
|
||||
return EVENT_ALLOW;
|
||||
}
|
||||
|
||||
EventReturn OnCheckAuthentication(Command *c, CommandSource *source, const std::vector<Anope::string> ¶ms, const Anope::string &account, const Anope::string &password) anope_override
|
||||
void OnCheckAuthentication(User *, IdentifyRequest *req) anope_override
|
||||
{
|
||||
const NickAlias *na = findnick(account);
|
||||
const NickAlias *na = findnick(req->GetAccount());
|
||||
if (na == NULL)
|
||||
return EVENT_CONTINUE;
|
||||
return;
|
||||
NickCore *nc = na->nc;
|
||||
|
||||
size_t pos = nc->pass.find(':');
|
||||
if (pos == Anope::string::npos)
|
||||
return EVENT_CONTINUE;
|
||||
return;
|
||||
Anope::string hash_method(nc->pass.begin(), nc->pass.begin() + pos);
|
||||
if (!hash_method.equals_cs("sha1"))
|
||||
return EVENT_CONTINUE;
|
||||
return;
|
||||
|
||||
Anope::string buf;
|
||||
this->OnEncrypt(password, buf);
|
||||
this->OnEncrypt(req->GetPassword(), buf);
|
||||
if (nc->pass.equals_cs(buf))
|
||||
{
|
||||
if (ModuleManager::FindFirstOf(ENCRYPTION) != this)
|
||||
enc_encrypt(password, nc->pass);
|
||||
return EVENT_ALLOW;
|
||||
enc_encrypt(req->GetPassword(), nc->pass);
|
||||
req->Success(this);
|
||||
}
|
||||
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -278,24 +278,24 @@ class ESHA256 : public Module
|
||||
return EVENT_ALLOW;
|
||||
}
|
||||
|
||||
EventReturn OnCheckAuthentication(Command *c, CommandSource *source, const std::vector<Anope::string> ¶ms, const Anope::string &account, const Anope::string &password) anope_override
|
||||
void OnCheckAuthentication(User *, IdentifyRequest *req) anope_override
|
||||
{
|
||||
const NickAlias *na = findnick(account);
|
||||
const NickAlias *na = findnick(req->GetAccount());
|
||||
if (na == NULL)
|
||||
return EVENT_CONTINUE;
|
||||
return;
|
||||
NickCore *nc = na->nc;
|
||||
|
||||
size_t pos = nc->pass.find(':');
|
||||
if (pos == Anope::string::npos)
|
||||
return EVENT_CONTINUE;
|
||||
return;
|
||||
Anope::string hash_method(nc->pass.begin(), nc->pass.begin() + pos);
|
||||
if (!hash_method.equals_cs("sha256"))
|
||||
return EVENT_CONTINUE;
|
||||
return;
|
||||
|
||||
GetIVFromPass(nc->pass);
|
||||
use_iv = true;
|
||||
Anope::string buf;
|
||||
this->OnEncrypt(password, buf);
|
||||
this->OnEncrypt(req->GetPassword(), buf);
|
||||
|
||||
if (nc->pass.equals_cs(buf))
|
||||
{
|
||||
@@ -303,11 +303,9 @@ class ESHA256 : public Module
|
||||
* we want to re-encrypt the pass with the new encryption
|
||||
*/
|
||||
if (ModuleManager::FindFirstOf(ENCRYPTION) != this)
|
||||
enc_encrypt(password, nc->pass);
|
||||
return EVENT_ALLOW;
|
||||
enc_encrypt(req->GetPassword(), nc->pass);
|
||||
req->Success(this);
|
||||
}
|
||||
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+19
-2
@@ -21,6 +21,23 @@ struct HTTPReply
|
||||
|
||||
HTTPReply() : error(HTTP_ERROR_OK), length(0) { }
|
||||
|
||||
HTTPReply(const HTTPReply& other) : error(other.error), length(other.length)
|
||||
{
|
||||
content_type = other.content_type;
|
||||
headers = other.headers;
|
||||
cookies = other.cookies;
|
||||
|
||||
for (unsigned i = 0; i < other.out.size(); ++i)
|
||||
out.push_back(new Data(other.out[i]->buf, other.out[i]->len));
|
||||
}
|
||||
|
||||
~HTTPReply()
|
||||
{
|
||||
for (unsigned i = 0; i < out.size(); ++i)
|
||||
delete out[i];
|
||||
out.clear();
|
||||
}
|
||||
|
||||
struct Data
|
||||
{
|
||||
char *buf;
|
||||
@@ -87,10 +104,10 @@ class HTTPPage : public Base
|
||||
* @param The HTTP header sent from the client to request the page
|
||||
* @param The HTTP header that will be sent back to the client
|
||||
*/
|
||||
virtual void OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &) = 0;
|
||||
virtual bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &) = 0;
|
||||
};
|
||||
|
||||
class HTTPClient : public ClientSocket, public BufferedSocket, public BinarySocket
|
||||
class HTTPClient : public ClientSocket, public BufferedSocket, public BinarySocket, public Base
|
||||
{
|
||||
protected:
|
||||
void WriteClient(const Anope::string &message)
|
||||
|
||||
@@ -35,7 +35,7 @@ static Anope::string GetStatusFromCode(HTTPError err)
|
||||
return "501 Not Implemented";
|
||||
}
|
||||
|
||||
class MyHTTPClient : public HTTPClient, public Base
|
||||
class MyHTTPClient : public HTTPClient
|
||||
{
|
||||
HTTPProvider *provider;
|
||||
HTTPMessage header;
|
||||
@@ -78,9 +78,8 @@ class MyHTTPClient : public HTTPClient, public Base
|
||||
|
||||
HTTPReply reply;
|
||||
|
||||
this->page->OnRequest(this->provider, this->page_name, this, this->header, reply);
|
||||
|
||||
this->SendReply(&reply);
|
||||
if (this->page->OnRequest(this->provider, this->page_name, this, this->header, reply))
|
||||
this->SendReply(&reply);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
#include "nickserv.h"
|
||||
#include "ldap.h"
|
||||
|
||||
static Module *me;
|
||||
|
||||
static Anope::string basedn;
|
||||
static Anope::string search_filter;
|
||||
static Anope::string object_class;
|
||||
@@ -10,17 +12,21 @@ static Anope::string username_attribute;
|
||||
|
||||
struct IdentifyInfo
|
||||
{
|
||||
dynamic_reference<Command> command;
|
||||
CommandSource source;
|
||||
std::vector<Anope::string> params;
|
||||
Anope::string account;
|
||||
Anope::string pass;
|
||||
Anope::string dn;
|
||||
dynamic_reference<User> user;
|
||||
IdentifyRequest *req;
|
||||
service_reference<LDAPProvider> lprov;
|
||||
bool admin_bind;
|
||||
Anope::string dn;
|
||||
|
||||
IdentifyInfo(Command *c, CommandSource &s, const std::vector<Anope::string> &pa, const Anope::string &a, const Anope::string &p, service_reference<LDAPProvider> &lp) :
|
||||
command(c), source(s), params(pa), account(a), pass(p), lprov(lp), admin_bind(true) { }
|
||||
IdentifyInfo(User *u, IdentifyRequest *r, service_reference<LDAPProvider> &lp) : user(u), req(r), lprov(lp), admin_bind(true)
|
||||
{
|
||||
req->Hold(me);
|
||||
}
|
||||
|
||||
~IdentifyInfo()
|
||||
{
|
||||
req->Release(me);
|
||||
}
|
||||
};
|
||||
|
||||
class IdentifyInterface : public LDAPInterface
|
||||
@@ -46,9 +52,9 @@ class IdentifyInterface : public LDAPInterface
|
||||
IdentifyInfo *ii = it->second;
|
||||
this->requests.erase(it);
|
||||
|
||||
if (!ii->source.GetUser() || !ii->command || !ii->lprov)
|
||||
if (!ii->lprov)
|
||||
{
|
||||
delete this;
|
||||
delete ii;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -63,69 +69,55 @@ class IdentifyInterface : public LDAPInterface
|
||||
const LDAPAttributes &attr = r.get(0);
|
||||
ii->dn = attr.get("dn");
|
||||
Log(LOG_DEBUG) << "m_ldap_authenticationn: binding as " << ii->dn;
|
||||
LDAPQuery id = ii->lprov->Bind(this, ii->dn, ii->pass);
|
||||
LDAPQuery id = ii->lprov->Bind(this, ii->dn, ii->req->GetPassword());
|
||||
this->Add(id, ii);
|
||||
return;
|
||||
}
|
||||
catch (const LDAPException &ex)
|
||||
{
|
||||
Log() << "m_ldap_authentication: Error binding after search: " << ex.GetReason();
|
||||
delete ii;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
User *u = ii->source.GetUser();
|
||||
Command *c = ii->command;
|
||||
|
||||
u->Extend("m_ldap_authentication_error", NULL);
|
||||
|
||||
c->Execute(ii->source, ii->params);
|
||||
|
||||
delete ii;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case LDAPResult::QUERY_BIND:
|
||||
{
|
||||
if (ii->admin_bind)
|
||||
{
|
||||
Anope::string sf = search_filter.replace_all_cs("%account", ii->account).replace_all_cs("%object_class", object_class);
|
||||
Anope::string sf = search_filter.replace_all_cs("%account", ii->req->GetAccount()).replace_all_cs("%object_class", object_class);
|
||||
Log(LOG_DEBUG) << "m_ldap_authentication: searching for " << sf;
|
||||
LDAPQuery id = ii->lprov->Search(this, basedn, sf);
|
||||
this->Add(id, ii);
|
||||
ii->admin_bind = false;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
User *u = ii->source.GetUser();
|
||||
Command *c = ii->command;
|
||||
|
||||
u->Extend("m_ldap_authentication_authenticated", NULL);
|
||||
|
||||
NickAlias *na = findnick(ii->account);
|
||||
NickAlias *na = findnick(ii->req->GetAccount());
|
||||
if (na == NULL)
|
||||
{
|
||||
na = new NickAlias(ii->account, new NickCore(ii->account));
|
||||
if (Config->NSAddAccessOnReg)
|
||||
na->nc->AddAccess(create_mask(u));
|
||||
|
||||
BotInfo *bi = findbot(Config->NickServ);
|
||||
if (bi)
|
||||
u->SendMessage(bi, _("Your account \002%s\002 has been successfully created."), na->nick.c_str());
|
||||
}
|
||||
na = new NickAlias(ii->req->GetAccount(), new NickCore(ii->req->GetAccount()));
|
||||
if (ii->user)
|
||||
{
|
||||
if (Config->NSAddAccessOnReg)
|
||||
na->nc->AddAccess(create_mask(ii->user));
|
||||
|
||||
const BotInfo *bi = findbot(Config->NickServ);
|
||||
if (bi)
|
||||
ii->user->SendMessage(bi, _("Your account \002%s\002 has been successfully created."), na->nick.c_str());
|
||||
}
|
||||
}
|
||||
na->nc->Extend("m_ldap_authentication_dn", new ExtensibleItemClass<Anope::string>(ii->dn));
|
||||
|
||||
enc_encrypt(ii->pass, na->nc->pass);
|
||||
|
||||
c->Execute(ii->source, ii->params);
|
||||
delete ii;
|
||||
|
||||
ii->req->Success(me);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
delete ii;
|
||||
break;
|
||||
}
|
||||
|
||||
delete ii;
|
||||
}
|
||||
|
||||
void OnError(const LDAPResult &r) anope_override
|
||||
@@ -135,20 +127,6 @@ class IdentifyInterface : public LDAPInterface
|
||||
return;
|
||||
IdentifyInfo *ii = it->second;
|
||||
this->requests.erase(it);
|
||||
|
||||
if (!ii->source.GetUser() || !ii->command)
|
||||
{
|
||||
delete ii;
|
||||
return;
|
||||
}
|
||||
|
||||
User *u = ii->source.GetUser();
|
||||
Command *c = ii->command;
|
||||
|
||||
u->Extend("m_ldap_authentication_error", NULL);
|
||||
|
||||
c->Execute(ii->source, ii->params);
|
||||
|
||||
delete ii;
|
||||
}
|
||||
};
|
||||
@@ -235,6 +213,8 @@ class NSIdentifyLDAP : public Module
|
||||
{
|
||||
this->SetAuthor("Anope");
|
||||
|
||||
me = this;
|
||||
|
||||
Implementation i[] = { I_OnReload, I_OnPreCommand, I_OnCheckAuthentication, I_OnNickIdentify, I_OnNickRegister };
|
||||
ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation));
|
||||
ModuleManager::SetPriority(this, PRIORITY_FIRST);
|
||||
@@ -267,28 +247,12 @@ class NSIdentifyLDAP : public Module
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
|
||||
EventReturn OnCheckAuthentication(Command *c, CommandSource *source, const std::vector<Anope::string> ¶ms, const Anope::string &account, const Anope::string &password) anope_override
|
||||
void OnCheckAuthentication(User *u, IdentifyRequest *req) anope_override
|
||||
{
|
||||
if (!this->ldap)
|
||||
return;
|
||||
|
||||
if (c == NULL || source == NULL || !this->ldap)
|
||||
return EVENT_CONTINUE;
|
||||
|
||||
User *u = source->GetUser();
|
||||
if (!u)
|
||||
return EVENT_CONTINUE;
|
||||
|
||||
if (u->HasExt("m_ldap_authentication_authenticated"))
|
||||
{
|
||||
u->Shrink("m_ldap_authentication_authenticated");
|
||||
return EVENT_ALLOW;
|
||||
}
|
||||
else if (u->HasExt("m_ldap_authentication_error"))
|
||||
{
|
||||
u->Shrink("m_ldap_authentication_error");
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
|
||||
IdentifyInfo *ii = new IdentifyInfo(c, *source, params, account, password, this->ldap);
|
||||
IdentifyInfo *ii = new IdentifyInfo(u, req, this->ldap);
|
||||
try
|
||||
{
|
||||
LDAPQuery id = this->ldap->BindAsAdmin(&this->iinterface);
|
||||
@@ -298,10 +262,7 @@ class NSIdentifyLDAP : public Module
|
||||
{
|
||||
delete ii;
|
||||
Log() << "ns_identify_ldap: " << ex.GetReason();
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
|
||||
return EVENT_STOP;
|
||||
}
|
||||
|
||||
void OnNickIdentify(User *u) anope_override
|
||||
|
||||
@@ -1,71 +1,71 @@
|
||||
#include "module.h"
|
||||
#include "sql.h"
|
||||
|
||||
static Module *me;
|
||||
|
||||
class SQLAuthenticationResult : public SQLInterface
|
||||
{
|
||||
dynamic_reference<Command> cmd;
|
||||
CommandSource source;
|
||||
std::vector<Anope::string> params;
|
||||
dynamic_reference<User> user;
|
||||
Anope::string account;
|
||||
IdentifyRequest *req;
|
||||
|
||||
public:
|
||||
SQLAuthenticationResult(Module *m, Command *c, CommandSource &s, const std::vector<Anope::string> &p, User *u, const Anope::string &a) : SQLInterface(m), cmd(c), source(s), params(p), user(u), account(a) { }
|
||||
SQLAuthenticationResult(User *u, IdentifyRequest *r) : SQLInterface(me), user(u), req(r)
|
||||
{
|
||||
req->Hold(me);
|
||||
}
|
||||
|
||||
~SQLAuthenticationResult()
|
||||
{
|
||||
req->Release(me);
|
||||
}
|
||||
|
||||
void OnResult(const SQLResult &r) anope_override
|
||||
{
|
||||
if (user && cmd)
|
||||
if (r.Rows() == 0)
|
||||
{
|
||||
Anope::string email;
|
||||
Log(LOG_DEBUG) << "m_sql_authentication: Unsuccessful authentication for " << req->GetAccount();
|
||||
delete this;
|
||||
return;
|
||||
}
|
||||
|
||||
if (r.Rows() > 0)
|
||||
Log(LOG_DEBUG) << "m_sql_authentication: Successful authentication for " << req->GetAccount();
|
||||
|
||||
Anope::string email;
|
||||
try
|
||||
{
|
||||
email = r.Get(0, "email");
|
||||
}
|
||||
catch (const SQLException &) { }
|
||||
|
||||
const BotInfo *bi = findbot(Config->NickServ);
|
||||
NickAlias *na = findnick(req->GetAccount());
|
||||
if (na == NULL)
|
||||
{
|
||||
na = new NickAlias(req->GetAccount(), new NickCore(req->GetAccount()));
|
||||
if (user)
|
||||
{
|
||||
user->Extend("m_sql_authentication_success", NULL);
|
||||
|
||||
try
|
||||
{
|
||||
email = r.Get(0, "email");
|
||||
}
|
||||
catch (const SQLException &) { }
|
||||
}
|
||||
else
|
||||
user->Extend("m_sql_authentication_failed", NULL);
|
||||
|
||||
BotInfo *bi = findbot(Config->NickServ);
|
||||
NickAlias *na = findnick(account);
|
||||
if (na == NULL)
|
||||
{
|
||||
na = new NickAlias(account, new NickCore(account));
|
||||
if (Config->NSAddAccessOnReg)
|
||||
na->nc->AddAccess(create_mask(user));
|
||||
|
||||
if (bi)
|
||||
user->SendMessage(bi, _("Your account \002%s\002 has been successfully created."), na->nick.c_str());
|
||||
}
|
||||
|
||||
if (!email.empty() && email != na->nc->email)
|
||||
{
|
||||
na->nc->email = email;
|
||||
if (bi)
|
||||
user->SendMessage(bi, _("Your email has been updated to \002%s\002."), email.c_str());
|
||||
}
|
||||
|
||||
cmd->Execute(source, params);
|
||||
}
|
||||
|
||||
if (!email.empty() && email != na->nc->email)
|
||||
{
|
||||
na->nc->email = email;
|
||||
if (user && bi)
|
||||
user->SendMessage(bi, _("Your email has been updated to \002%s\002."), email.c_str());
|
||||
}
|
||||
|
||||
req->Success(me);
|
||||
delete this;
|
||||
}
|
||||
|
||||
void OnError(const SQLResult &r) anope_override
|
||||
{
|
||||
Log() << "m_sql_authentication: Error executing query " << r.GetQuery().query << ": " << r.GetError();
|
||||
|
||||
if (user && cmd)
|
||||
{
|
||||
user->Extend("m_sql_authentication_failed", NULL);
|
||||
cmd->Execute(source, params);
|
||||
}
|
||||
|
||||
delete this;
|
||||
}
|
||||
};
|
||||
@@ -84,6 +84,8 @@ class ModuleSQLAuthentication : public Module
|
||||
{
|
||||
this->SetAuthor("Anope");
|
||||
|
||||
me = this;
|
||||
|
||||
Implementation i[] = { I_OnReload, I_OnPreCommand, I_OnCheckAuthentication };
|
||||
ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation));
|
||||
|
||||
@@ -113,37 +115,32 @@ class ModuleSQLAuthentication : public Module
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
|
||||
EventReturn OnCheckAuthentication(Command *c, CommandSource *source, const std::vector<Anope::string> ¶ms, const Anope::string &account, const Anope::string &password) anope_override
|
||||
void OnCheckAuthentication(User *u, IdentifyRequest *req) anope_override
|
||||
{
|
||||
if (!source || !source->GetUser())
|
||||
return EVENT_CONTINUE;
|
||||
else if (!this->SQL)
|
||||
if (!this->SQL)
|
||||
{
|
||||
Log() << "m_sql_authentication: Unable to find SQL engine";
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
else if (source->GetUser()->HasExt("m_sql_authentication_success"))
|
||||
{
|
||||
source->GetUser()->Shrink("m_sql_authentication_success");
|
||||
return EVENT_ALLOW;
|
||||
}
|
||||
else if (source->GetUser()->HasExt("m_sql_authentication_failed"))
|
||||
{
|
||||
source->GetUser()->Shrink("m_sql_authentication_failed");
|
||||
return EVENT_CONTINUE;
|
||||
return;
|
||||
}
|
||||
|
||||
SQLQuery q(this->query);
|
||||
q.setValue("a", account);
|
||||
q.setValue("p", password);
|
||||
q.setValue("n", source->GetNick());
|
||||
q.setValue("i", source->GetUser()->ip);
|
||||
q.setValue("a", req->GetAccount());
|
||||
q.setValue("p", req->GetPassword());
|
||||
if (u)
|
||||
{
|
||||
q.setValue("n", u->nick);
|
||||
q.setValue("i", u->ip);
|
||||
}
|
||||
else
|
||||
{
|
||||
q.setValue("n", "");
|
||||
q.setValue("i", "");
|
||||
}
|
||||
|
||||
this->SQL->Run(new SQLAuthenticationResult(this, c, *source, params, source->GetUser(), account), q);
|
||||
|
||||
Log(LOG_DEBUG) << "m_sql_authentication: Checking authentication for " << account;
|
||||
this->SQL->Run(new SQLAuthenticationResult(u, req), q);
|
||||
|
||||
return EVENT_STOP;
|
||||
Log(LOG_DEBUG) << "m_sql_authentication: Checking authentication for " << req->GetAccount();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,37 @@
|
||||
#include "module.h"
|
||||
#include "xmlrpc.h"
|
||||
|
||||
class XMLRPCIdentifyRequest : public IdentifyRequest
|
||||
{
|
||||
XMLRPCRequest request;
|
||||
dynamic_reference<XMLRPCServiceInterface> xinterface;
|
||||
dynamic_reference<XMLRPCClientSocket> source;
|
||||
|
||||
public:
|
||||
XMLRPCIdentifyRequest(XMLRPCRequest& req, XMLRPCServiceInterface* iface, XMLRPCClientSocket* s, const Anope::string &acc, const Anope::string &pass) : IdentifyRequest(acc, pass), request(req), xinterface(iface), source(s) { }
|
||||
|
||||
void OnSuccess() anope_override
|
||||
{
|
||||
if (!xinterface || !source)
|
||||
return;
|
||||
|
||||
request.reply("result", "Success");
|
||||
request.reply("account", GetAccount());
|
||||
|
||||
xinterface->Reply(source, &request);
|
||||
}
|
||||
|
||||
void OnFail() anope_override
|
||||
{
|
||||
if (!xinterface || !source)
|
||||
return;
|
||||
|
||||
request.reply("error", "Invalid password");
|
||||
|
||||
xinterface->Reply(source, &request);
|
||||
}
|
||||
};
|
||||
|
||||
class MyXMLRPCEvent : public XMLRPCEvent
|
||||
{
|
||||
public:
|
||||
@@ -77,22 +108,9 @@ class MyXMLRPCEvent : public XMLRPCEvent
|
||||
request->reply("error", "Invalid parameters");
|
||||
else
|
||||
{
|
||||
const NickAlias *na = findnick(username);
|
||||
|
||||
if (!na)
|
||||
request->reply("error", "Invalid account");
|
||||
else
|
||||
{
|
||||
EventReturn MOD_RESULT;
|
||||
FOREACH_RESULT(I_OnCheckAuthentication, OnCheckAuthentication(NULL, NULL, std::vector<Anope::string>(), na->nc->display, password));
|
||||
if (MOD_RESULT == EVENT_ALLOW)
|
||||
{
|
||||
request->reply("result", "Success");
|
||||
request->reply("account", na->nc->display);
|
||||
}
|
||||
else
|
||||
request->reply("error", "Invalid password");
|
||||
}
|
||||
XMLRPCIdentifyRequest *req = new XMLRPCIdentifyRequest(*request, iface, source, username, password);
|
||||
FOREACH_MOD(I_OnCheckAuthentication, OnCheckAuthentication(NULL, req));
|
||||
req->Dispatch();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ WebCPanel::ChanServ::Access::Access(const Anope::string &cat, const Anope::strin
|
||||
{
|
||||
}
|
||||
|
||||
void WebCPanel::ChanServ::Access::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply, NickAlias *na, TemplateFileServer::Replacements &replacements)
|
||||
bool WebCPanel::ChanServ::Access::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply, NickAlias *na, TemplateFileServer::Replacements &replacements)
|
||||
{
|
||||
const Anope::string &chname = message.get_data["channel"];
|
||||
|
||||
@@ -19,19 +19,19 @@ void WebCPanel::ChanServ::Access::OnRequest(HTTPProvider *server, const Anope::s
|
||||
{
|
||||
reply.error = HTTP_FOUND;
|
||||
reply.headers["Location"] = "http://" + message.headers["Host"] + "/chanserv/info";
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
ChannelInfo *ci = cs_findchan(chname);
|
||||
|
||||
if (!ci)
|
||||
return;
|
||||
return true;
|
||||
|
||||
AccessGroup u_access = ci->AccessFor(na->nc);
|
||||
bool has_priv = na->nc->IsServicesOper() && na->nc->o->ot->HasPriv("chanserv/access/modify");
|
||||
|
||||
if (!u_access.HasPriv("ACCESS_LIST") && !has_priv)
|
||||
return;
|
||||
return true;
|
||||
|
||||
const ChanAccess *highest = u_access.Highest();
|
||||
|
||||
@@ -136,6 +136,7 @@ void WebCPanel::ChanServ::Access::OnRequest(HTTPProvider *server, const Anope::s
|
||||
|
||||
TemplateFileServer page("chanserv/access.html");
|
||||
page.Serve(server, page_name, client, message, reply, replacements);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::set<Anope::string> WebCPanel::ChanServ::Access::GetData() anope_override
|
||||
|
||||
@@ -16,7 +16,7 @@ class Access : public WebPanelProtectedPage
|
||||
public:
|
||||
Access(const Anope::string &cat, const Anope::string &u);
|
||||
|
||||
void OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override;
|
||||
bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override;
|
||||
|
||||
std::set<Anope::string> GetData() anope_override;
|
||||
};
|
||||
|
||||
@@ -11,7 +11,7 @@ WebCPanel::ChanServ::Akick::Akick(const Anope::string &cat, const Anope::string
|
||||
{
|
||||
}
|
||||
|
||||
void WebCPanel::ChanServ::Akick::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply, NickAlias *na, TemplateFileServer::Replacements &replacements)
|
||||
bool WebCPanel::ChanServ::Akick::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply, NickAlias *na, TemplateFileServer::Replacements &replacements)
|
||||
{
|
||||
const Anope::string &chname = message.get_data["channel"];
|
||||
|
||||
@@ -19,19 +19,19 @@ void WebCPanel::ChanServ::Akick::OnRequest(HTTPProvider *server, const Anope::st
|
||||
{
|
||||
reply.error = HTTP_FOUND;
|
||||
reply.headers["Location"] = "http://" + message.headers["Host"] + "/chanserv/info";
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
ChannelInfo *ci = cs_findchan(chname);
|
||||
|
||||
if (!ci)
|
||||
return;
|
||||
return true;
|
||||
|
||||
AccessGroup u_access = ci->AccessFor(na->nc);
|
||||
bool has_priv = na->nc->IsServicesOper() && na->nc->o->ot->HasPriv("chanserv/access/modify");
|
||||
|
||||
if (!u_access.HasPriv("akick") && !has_priv)
|
||||
return;
|
||||
return true;
|
||||
|
||||
if (message.get_data["del"].empty() == false && message.get_data["mask"].empty() == false)
|
||||
{
|
||||
@@ -70,6 +70,7 @@ void WebCPanel::ChanServ::Akick::OnRequest(HTTPProvider *server, const Anope::st
|
||||
|
||||
TemplateFileServer page("chanserv/akick.html");
|
||||
page.Serve(server, page_name, client, message, reply, replacements);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::set<Anope::string> WebCPanel::ChanServ::Akick::GetData() anope_override
|
||||
|
||||
@@ -16,7 +16,7 @@ class Akick : public WebPanelProtectedPage
|
||||
public:
|
||||
Akick(const Anope::string &cat, const Anope::string &u);
|
||||
|
||||
void OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override;
|
||||
bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override;
|
||||
|
||||
std::set<Anope::string> GetData() anope_override;
|
||||
};
|
||||
|
||||
@@ -11,7 +11,7 @@ WebCPanel::ChanServ::Info::Info(const Anope::string &cat, const Anope::string &u
|
||||
{
|
||||
}
|
||||
|
||||
void WebCPanel::ChanServ::Info::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply, NickAlias *na, TemplateFileServer::Replacements &replacements)
|
||||
bool WebCPanel::ChanServ::Info::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply, NickAlias *na, TemplateFileServer::Replacements &replacements)
|
||||
{
|
||||
// XXX this is slightly inefficient
|
||||
for (registered_channel_map::const_iterator it = RegisteredChannelList->begin(), it_end = RegisteredChannelList->end(); it != it_end; ++it)
|
||||
@@ -25,8 +25,8 @@ void WebCPanel::ChanServ::Info::OnRequest(HTTPProvider *server, const Anope::str
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TemplateFileServer page("chanserv/main.html");
|
||||
page.Serve(server, page_name, client, message, reply, replacements);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ class Info : public WebPanelProtectedPage
|
||||
public:
|
||||
Info(const Anope::string &cat, const Anope::string &u);
|
||||
|
||||
void OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override;
|
||||
bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ WebCPanel::ChanServ::Set::Set(const Anope::string &cat, const Anope::string &u)
|
||||
{
|
||||
}
|
||||
|
||||
void WebCPanel::ChanServ::Set::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply, NickAlias *na, TemplateFileServer::Replacements &replacements)
|
||||
bool WebCPanel::ChanServ::Set::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply, NickAlias *na, TemplateFileServer::Replacements &replacements)
|
||||
{
|
||||
const Anope::string &chname = message.get_data["channel"];
|
||||
|
||||
@@ -19,13 +19,13 @@ void WebCPanel::ChanServ::Set::OnRequest(HTTPProvider *server, const Anope::stri
|
||||
{
|
||||
reply.error = HTTP_FOUND;
|
||||
reply.headers["Location"] = "http://" + message.headers["Host"] + "/chanserv/info";
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
ChannelInfo *ci = cs_findchan(chname);
|
||||
|
||||
if (!ci || !ci->AccessFor(na->nc).HasPriv("SET"))
|
||||
return;
|
||||
return true;
|
||||
|
||||
if (message.post_data.empty() == false)
|
||||
{
|
||||
@@ -125,6 +125,7 @@ void WebCPanel::ChanServ::Set::OnRequest(HTTPProvider *server, const Anope::stri
|
||||
|
||||
TemplateFileServer page("chanserv/set.html");
|
||||
page.Serve(server, page_name, client, message, reply, replacements);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::set<Anope::string> WebCPanel::ChanServ::Set::GetData() anope_override
|
||||
|
||||
@@ -16,7 +16,7 @@ class Set : public WebPanelProtectedPage
|
||||
public:
|
||||
Set(const Anope::string &cat, const Anope::string &u);
|
||||
|
||||
void OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override;
|
||||
bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override;
|
||||
|
||||
std::set<Anope::string> GetData() anope_override;
|
||||
};
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
#include "../webcpanel.h"
|
||||
|
||||
void WebCPanel::Confirm::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply)
|
||||
bool WebCPanel::Confirm::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply)
|
||||
{
|
||||
TemplateFileServer::Replacements replacements;
|
||||
const Anope::string &user = message.post_data["username"], &pass = message.post_data["password"], &email = message.post_data["email"];
|
||||
@@ -27,5 +27,6 @@ void WebCPanel::Confirm::OnRequest(HTTPProvider *server, const Anope::string &pa
|
||||
TemplateFileServer page("confirm.html");
|
||||
|
||||
page.Serve(server, page_name, client, message, reply, replacements);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ class Confirm : public WebPanelPage
|
||||
public:
|
||||
Confirm(const Anope::string &u) : WebPanelPage(u) { }
|
||||
|
||||
void OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &) anope_override;
|
||||
bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &) anope_override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -7,7 +7,75 @@
|
||||
|
||||
#include "../webcpanel.h"
|
||||
|
||||
void WebCPanel::Index::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply)
|
||||
class WebpanelRequest : public IdentifyRequest
|
||||
{
|
||||
HTTPReply reply;
|
||||
HTTPMessage message;
|
||||
dynamic_reference<HTTPProvider> server;
|
||||
Anope::string page_name;
|
||||
dynamic_reference<HTTPClient> client;
|
||||
TemplateFileServer::Replacements replacements;
|
||||
|
||||
public:
|
||||
WebpanelRequest(HTTPReply &r, HTTPMessage &m, HTTPProvider *s, const Anope::string &p_n, HTTPClient *c, TemplateFileServer::Replacements &re, const Anope::string &user, const Anope::string &pass) : IdentifyRequest(user, pass), reply(r), message(m), server(s), page_name(p_n), client(c), replacements(re) { }
|
||||
|
||||
void OnSuccess() anope_override
|
||||
{
|
||||
if (!client)
|
||||
return;
|
||||
NickAlias *na = findnick(this->GetAccount());
|
||||
if (!na)
|
||||
{
|
||||
this->OnFail();
|
||||
return;
|
||||
}
|
||||
|
||||
Anope::string id;
|
||||
for (int i = 0; i < 64; ++i)
|
||||
{
|
||||
char c;
|
||||
do
|
||||
c = 48 + (rand() % 75);
|
||||
while (!isalnum(c));
|
||||
id += c;
|
||||
}
|
||||
|
||||
na->Extend("webcpanel_id", new ExtensibleItemClass<Anope::string>(id));
|
||||
na->Extend("webcpanel_ip", new ExtensibleItemClass<Anope::string>(client->GetIP()));
|
||||
|
||||
{
|
||||
HTTPReply::cookie c;
|
||||
c.push_back(std::make_pair("account", na->nick));
|
||||
c.push_back(std::make_pair("Path", "/"));
|
||||
reply.cookies.push_back(c);
|
||||
}
|
||||
|
||||
{
|
||||
HTTPReply::cookie c;
|
||||
c.push_back(std::make_pair("id", id));
|
||||
c.push_back(std::make_pair("Path", "/"));
|
||||
reply.cookies.push_back(c);
|
||||
}
|
||||
|
||||
reply.error = HTTP_FOUND;
|
||||
reply.headers["Location"] = "http://" + message.headers["Host"] + "/nickserv/info";
|
||||
|
||||
client->SendReply(&reply);
|
||||
}
|
||||
|
||||
void OnFail() anope_override
|
||||
{
|
||||
if (!client)
|
||||
return;
|
||||
replacements["INVALID_LOGIN"] = "Invalid username or password";
|
||||
TemplateFileServer page("login.html");
|
||||
page.Serve(server, page_name, client, message, reply, replacements);
|
||||
|
||||
client->SendReply(&reply);
|
||||
}
|
||||
};
|
||||
|
||||
bool WebCPanel::Index::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply)
|
||||
{
|
||||
TemplateFileServer::Replacements replacements;
|
||||
const Anope::string &user = message.post_data["username"], &pass = message.post_data["password"];
|
||||
@@ -18,56 +86,14 @@ void WebCPanel::Index::OnRequest(HTTPProvider *server, const Anope::string &page
|
||||
{
|
||||
// Rate limit check.
|
||||
|
||||
NickAlias *na = findnick(user);
|
||||
|
||||
EventReturn MOD_RESULT = EVENT_CONTINUE;
|
||||
|
||||
if (na)
|
||||
{
|
||||
FOREACH_RESULT(I_OnCheckAuthentication, OnCheckAuthentication(NULL, NULL, std::vector<Anope::string>(), na->nc->display, pass));
|
||||
}
|
||||
|
||||
if (MOD_RESULT == EVENT_ALLOW)
|
||||
{
|
||||
Anope::string id;
|
||||
for (int i = 0; i < 64; ++i)
|
||||
{
|
||||
char c;
|
||||
do
|
||||
c = 48 + (rand() % 75);
|
||||
while (!isalnum(c));
|
||||
id += c;
|
||||
}
|
||||
|
||||
na->Extend("webcpanel_id", new ExtensibleItemClass<Anope::string>(id));
|
||||
na->Extend("webcpanel_ip", new ExtensibleItemClass<Anope::string>(client->GetIP()));
|
||||
|
||||
{
|
||||
HTTPReply::cookie c;
|
||||
c.push_back(std::make_pair("account", na->nick));
|
||||
c.push_back(std::make_pair("Path", "/"));
|
||||
reply.cookies.push_back(c);
|
||||
}
|
||||
|
||||
{
|
||||
HTTPReply::cookie c;
|
||||
c.push_back(std::make_pair("id", id));
|
||||
c.push_back(std::make_pair("Path", "/"));
|
||||
reply.cookies.push_back(c);
|
||||
}
|
||||
|
||||
reply.error = HTTP_FOUND;
|
||||
reply.headers["Location"] = "http://" + message.headers["Host"] + "/nickserv/info";
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
replacements["INVALID_LOGIN"] = "Invalid username or password";
|
||||
}
|
||||
WebpanelRequest *req = new WebpanelRequest(reply, message, server, page_name, client, replacements, user, pass);
|
||||
FOREACH_MOD(I_OnCheckAuthentication, OnCheckAuthentication(NULL, req));
|
||||
req->Dispatch();
|
||||
return false;
|
||||
}
|
||||
|
||||
TemplateFileServer page("login.html");
|
||||
|
||||
page.Serve(server, page_name, client, message, reply, replacements);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ class Index : public WebPanelPage
|
||||
public:
|
||||
Index(const Anope::string &u) : WebPanelPage(u) { }
|
||||
|
||||
void OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &) anope_override;
|
||||
bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &) anope_override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -11,12 +11,13 @@ WebCPanel::Logout::Logout(const Anope::string &u) : WebPanelProtectedPage("", u)
|
||||
{
|
||||
}
|
||||
|
||||
void WebCPanel::Logout::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply, NickAlias *na, TemplateFileServer::Replacements &replacements)
|
||||
bool WebCPanel::Logout::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply, NickAlias *na, TemplateFileServer::Replacements &replacements)
|
||||
{
|
||||
na->Shrink("webcpanel_id");
|
||||
na->Shrink("webcpanel_ip");
|
||||
|
||||
reply.error = HTTP_FOUND;
|
||||
reply.headers["Location"] = "http://" + message.headers["Host"];
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ class Logout : public WebPanelProtectedPage
|
||||
public:
|
||||
Logout(const Anope::string &u);
|
||||
|
||||
void OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override;
|
||||
bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ WebCPanel::MemoServ::Memos::Memos(const Anope::string &cat, const Anope::string
|
||||
{
|
||||
}
|
||||
|
||||
void WebCPanel::MemoServ::Memos::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply, NickAlias *na, TemplateFileServer::Replacements &replacements)
|
||||
bool WebCPanel::MemoServ::Memos::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply, NickAlias *na, TemplateFileServer::Replacements &replacements)
|
||||
{
|
||||
const Anope::string &chname = message.get_data["channel"];
|
||||
ChannelInfo *ci;
|
||||
@@ -117,5 +117,6 @@ void WebCPanel::MemoServ::Memos::OnRequest(HTTPProvider *server, const Anope::st
|
||||
|
||||
TemplateFileServer page("memoserv/memos.html");
|
||||
page.Serve(server, page_name, client, message, reply, replacements);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ class Memos : public WebPanelProtectedPage
|
||||
public:
|
||||
Memos(const Anope::string &cat, const Anope::string &u);
|
||||
|
||||
void OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override;
|
||||
bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ WebCPanel::NickServ::Access::Access(const Anope::string &cat, const Anope::strin
|
||||
{
|
||||
}
|
||||
|
||||
void WebCPanel::NickServ::Access::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply, NickAlias *na, TemplateFileServer::Replacements &replacements)
|
||||
bool WebCPanel::NickServ::Access::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply, NickAlias *na, TemplateFileServer::Replacements &replacements)
|
||||
{
|
||||
if (message.post_data.count("access") > 0)
|
||||
{
|
||||
@@ -35,5 +35,6 @@ void WebCPanel::NickServ::Access::OnRequest(HTTPProvider *server, const Anope::s
|
||||
|
||||
TemplateFileServer page("nickserv/access.html");
|
||||
page.Serve(server, page_name, client, message, reply, replacements);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ class Access : public WebPanelProtectedPage
|
||||
public:
|
||||
Access(const Anope::string &cat, const Anope::string &u);
|
||||
|
||||
void OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override;
|
||||
bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ WebCPanel::NickServ::Alist::Alist(const Anope::string &cat, const Anope::string
|
||||
{
|
||||
}
|
||||
|
||||
void WebCPanel::NickServ::Alist::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply, NickAlias *na, TemplateFileServer::Replacements &replacements)
|
||||
bool WebCPanel::NickServ::Alist::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply, NickAlias *na, TemplateFileServer::Replacements &replacements)
|
||||
{
|
||||
int chan_count = 0;
|
||||
|
||||
@@ -45,5 +45,6 @@ void WebCPanel::NickServ::Alist::OnRequest(HTTPProvider *server, const Anope::st
|
||||
|
||||
TemplateFileServer page("nickserv/alist.html");
|
||||
page.Serve(server, page_name, client, message, reply, replacements);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ class Alist : public WebPanelProtectedPage
|
||||
public:
|
||||
Alist(const Anope::string &cat, const Anope::string &u);
|
||||
|
||||
void OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override;
|
||||
bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ WebCPanel::NickServ::Cert::Cert(const Anope::string &cat, const Anope::string &u
|
||||
{
|
||||
}
|
||||
|
||||
void WebCPanel::NickServ::Cert::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply, NickAlias *na, TemplateFileServer::Replacements &replacements)
|
||||
bool WebCPanel::NickServ::Cert::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply, NickAlias *na, TemplateFileServer::Replacements &replacements)
|
||||
{
|
||||
if (message.post_data.count("certfp") > 0)
|
||||
{
|
||||
@@ -35,5 +35,6 @@ void WebCPanel::NickServ::Cert::OnRequest(HTTPProvider *server, const Anope::str
|
||||
|
||||
TemplateFileServer page("nickserv/cert.html");
|
||||
page.Serve(server, page_name, client, message, reply, replacements);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ class Cert : public WebPanelProtectedPage
|
||||
public:
|
||||
Cert(const Anope::string &cat, const Anope::string &u);
|
||||
|
||||
void OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override;
|
||||
bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ WebCPanel::NickServ::Info::Info(const Anope::string &cat, const Anope::string &u
|
||||
{
|
||||
}
|
||||
|
||||
void WebCPanel::NickServ::Info::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply, NickAlias *na, TemplateFileServer::Replacements &replacements)
|
||||
bool WebCPanel::NickServ::Info::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply, NickAlias *na, TemplateFileServer::Replacements &replacements)
|
||||
{
|
||||
if (message.post_data.empty() == false)
|
||||
{
|
||||
@@ -107,5 +107,6 @@ void WebCPanel::NickServ::Info::OnRequest(HTTPProvider *server, const Anope::str
|
||||
|
||||
TemplateFileServer page("nickserv/info.html");
|
||||
page.Serve(server, page_name, client, message, reply, replacements);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ class Info : public WebPanelProtectedPage
|
||||
public:
|
||||
Info(const Anope::string &cat, const Anope::string &u);
|
||||
|
||||
void OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override;
|
||||
bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ WebCPanel::OperServ::Akill::Akill(const Anope::string &cat, const Anope::string
|
||||
{
|
||||
}
|
||||
|
||||
void WebCPanel::OperServ::Akill::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply, NickAlias *na, TemplateFileServer::Replacements &replacements)
|
||||
bool WebCPanel::OperServ::Akill::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply, NickAlias *na, TemplateFileServer::Replacements &replacements)
|
||||
{
|
||||
|
||||
static service_reference<XLineManager> akills("XLineManager","xlinemanager/sgline");
|
||||
@@ -59,5 +59,6 @@ void WebCPanel::OperServ::Akill::OnRequest(HTTPProvider *server, const Anope::st
|
||||
|
||||
TemplateFileServer page("operserv/akill.html");
|
||||
page.Serve(server, page_name, client, message, reply, replacements);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ class Akill : public WebPanelProtectedPage
|
||||
public:
|
||||
Akill(const Anope::string &cat, const Anope::string &u);
|
||||
|
||||
void OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override;
|
||||
bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
#include "../webcpanel.h"
|
||||
|
||||
void WebCPanel::Register::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply)
|
||||
bool WebCPanel::Register::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply)
|
||||
{
|
||||
TemplateFileServer::Replacements replacements;
|
||||
|
||||
@@ -19,5 +19,6 @@ void WebCPanel::Register::OnRequest(HTTPProvider *server, const Anope::string &p
|
||||
TemplateFileServer page("register.html");
|
||||
|
||||
page.Serve(server, page_name, client, message, reply, replacements);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ class Register : public WebPanelPage
|
||||
public:
|
||||
Register(const Anope::string &u) : WebPanelPage(u) { }
|
||||
|
||||
void OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &) anope_override;
|
||||
bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &) anope_override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ StaticFileServer::StaticFileServer(const Anope::string &f_n, const Anope::string
|
||||
{
|
||||
}
|
||||
|
||||
void StaticFileServer::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply)
|
||||
bool StaticFileServer::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply)
|
||||
{
|
||||
int fd = open((template_base + "/" + this->file_name).c_str(), O_RDONLY);
|
||||
if (fd < 0)
|
||||
@@ -25,7 +25,7 @@ void StaticFileServer::OnRequest(HTTPProvider *server, const Anope::string &page
|
||||
Log(LOG_NORMAL, "httpd") << "Error serving file " << page_name << " (" << (template_base + "/" + this->file_name) << "): " << strerror(errno);
|
||||
|
||||
client->SendError(HTTP_PAGE_NOT_FOUND, "Page not found");
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
reply.content_type = this->GetContentType();
|
||||
@@ -37,5 +37,6 @@ void StaticFileServer::OnRequest(HTTPProvider *server, const Anope::string &page
|
||||
reply.Write(buffer, i);
|
||||
|
||||
close(fd);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,6 @@ class StaticFileServer : public HTTPPage
|
||||
public:
|
||||
StaticFileServer(const Anope::string &f_n, const Anope::string &u, const Anope::string &c_t);
|
||||
|
||||
void OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &) anope_override;
|
||||
bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &) anope_override;
|
||||
};
|
||||
|
||||
|
||||
@@ -239,5 +239,6 @@ void TemplateFileServer::Serve(HTTPProvider *server, const Anope::string &page_n
|
||||
}
|
||||
|
||||
reply.Write(finished);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ class WebPanelPage : public HTTPPage
|
||||
{
|
||||
}
|
||||
|
||||
virtual void OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &) = 0;
|
||||
virtual bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &) = 0;
|
||||
};
|
||||
|
||||
class WebPanelProtectedPage : public WebPanelPage
|
||||
@@ -78,14 +78,14 @@ class WebPanelProtectedPage : public WebPanelPage
|
||||
{
|
||||
}
|
||||
|
||||
void OnRequest(HTTPProvider *provider, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply) anope_override anope_final
|
||||
bool OnRequest(HTTPProvider *provider, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply) anope_override anope_final
|
||||
{
|
||||
service_reference<Panel> panel("Panel", "webcpanel");
|
||||
NickAlias *na;
|
||||
|
||||
if (!panel || !(na = panel->GetNickFromSession(client, message)))
|
||||
{
|
||||
return; // Access denied
|
||||
return true; // Access denied
|
||||
}
|
||||
|
||||
TemplateFileServer::Replacements replacements;
|
||||
@@ -123,10 +123,10 @@ class WebPanelProtectedPage : public WebPanelPage
|
||||
}
|
||||
}
|
||||
|
||||
this->OnRequest(provider, page_name, client, message, reply, na, replacements);
|
||||
return this->OnRequest(provider, page_name, client, message, reply, na, replacements);
|
||||
}
|
||||
|
||||
virtual void OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) = 0;
|
||||
virtual bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) = 0;
|
||||
|
||||
/* What get data should be appended to links in the navbar */
|
||||
virtual std::set<Anope::string> GetData() { return std::set<Anope::string>(); }
|
||||
|
||||
@@ -3,7 +3,7 @@ class XMLRPCClientSocket;
|
||||
class XMLRPCListenSocket;
|
||||
class XMLRPCServiceInterface;
|
||||
|
||||
class XMLRPCClientSocket : public ClientSocket, public BufferedSocket
|
||||
class XMLRPCClientSocket : public ClientSocket, public BufferedSocket, public Base
|
||||
{
|
||||
protected:
|
||||
Anope::string query;
|
||||
|
||||
@@ -52,6 +52,7 @@ Module::~Module()
|
||||
ModuleManager::DetachAll(this);
|
||||
/* Clear any active callbacks this module has */
|
||||
ModuleManager::ClearCallBacks(this);
|
||||
IdentifyRequest::ModuleUnload(this);
|
||||
|
||||
std::list<Module *>::iterator it = std::find(Modules.begin(), Modules.end(), this);
|
||||
if (it != Modules.end())
|
||||
|
||||
@@ -93,3 +93,62 @@ void change_core_display(NickCore *nc)
|
||||
change_core_display(nc, na->nick);
|
||||
}
|
||||
|
||||
std::set<IdentifyRequest *> IdentifyRequest::requests;
|
||||
|
||||
IdentifyRequest::IdentifyRequest(const Anope::string &acc, const Anope::string &pass) : account(acc), password(pass), dispatched(false), success(false)
|
||||
{
|
||||
requests.insert(this);
|
||||
}
|
||||
|
||||
IdentifyRequest::~IdentifyRequest()
|
||||
{
|
||||
requests.erase(this);
|
||||
}
|
||||
|
||||
void IdentifyRequest::Hold(Module *m)
|
||||
{
|
||||
holds.insert(m);
|
||||
}
|
||||
|
||||
void IdentifyRequest::Release(Module *m)
|
||||
{
|
||||
holds.erase(m);
|
||||
if (holds.empty() && dispatched)
|
||||
{
|
||||
if (!success)
|
||||
this->OnFail();
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
void IdentifyRequest::Success(Module *m)
|
||||
{
|
||||
if (!success)
|
||||
{
|
||||
this->OnSuccess();
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
|
||||
void IdentifyRequest::Dispatch()
|
||||
{
|
||||
if (holds.empty())
|
||||
{
|
||||
if (!success)
|
||||
this->OnFail();
|
||||
delete this;
|
||||
}
|
||||
else
|
||||
dispatched = true;
|
||||
}
|
||||
|
||||
void IdentifyRequest::ModuleUnload(Module *m)
|
||||
{
|
||||
for (std::set<IdentifyRequest *>::iterator it = requests.begin(), it_end = requests.end(); it != it_end;)
|
||||
{
|
||||
IdentifyRequest *ir = *it;
|
||||
++it;
|
||||
|
||||
ir->Release(m);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user