1
0
mirror of https://github.com/anope/anope.git synced 2026-06-30 00:36:37 +02:00

Removed nickrequests, instead have unconfirmed registrations. Also made ns_resetpass allow remote-id to get past things such as kill immed.

This commit is contained in:
Adam
2011-03-05 17:23:22 -05:00
parent 90e5d0feaa
commit 6fe2d8af97
41 changed files with 374 additions and 627 deletions
+9 -3
View File
@@ -939,6 +939,12 @@ nickserv
*/
forceemail = yes
/*
* Require users who change their email address to confirm they
* own it.
*/
confirmemailchanges = no
/*
* Require an e-mail to be sent to the user before they can register their nick.
*/
@@ -1018,12 +1024,12 @@ nickserv
#forbidexpire = 90d
/*
* The length of time a user gets to enter the confirmation code which has been e-mailed
* to them before the nick will be released for general use again.
* The length of time a user using an unconfirmed account has
* before the account will be released for general use again.
*
* This directive is only required if the e-mail registration option is enabled.
*/
#preregexpire = 1d
#unconfirmedexpire = 1d
/*
* The maximum number of nicks allowed in a group.
-15
View File
@@ -290,21 +290,6 @@ CREATE TABLE IF NOT EXISTS `anope_ns_core_metadata` (
-- --------------------------------------------------------
--
-- Table structure for table `anope_ns_request`
--
CREATE TABLE IF NOT EXISTS `anope_ns_request` (
`nick` varchar(255) NOT NULL DEFAULT '',
`passcode` text NOT NULL,
`password` text NOT NULL,
`email` text NOT NULL,
`requested` int(10) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`nick`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Table structure for table `anope_os_akills`
--
+7 -1
View File
@@ -2,11 +2,17 @@ Anope Version 1.9.4
--------------------
A Automatically set channel founder to the user with the highest access if there is no successor
A /chanserv clone command to copy settings from one channel to another.
A /chanserv mode command
A Ability for users to delete their own access in channels
A Ability for users with registrations pending to drop their registrations with /nickserv drop
A Added support for Plexus 3
A Readded in support for /cs op/deop/etc to op/deop you in all channels
A Added support for ngIRCd
A Added LDAP support
A Added live SQL support
A Added support for learning tracking/storing/locking all modes at runtime
A Added m_alias
A Added support for XMLRPC queries
A Added /botserv set msg
F Changed the GHOST command to not allow ghosting unidentified users if the RECOVER command exists
F Some failed logic in /operserv exception that prevents proper exceptions from being added
F Fixed the anope_os_sxlines MySQL table and code to work after restarting
+9 -2
View File
@@ -1,5 +1,6 @@
Anope Version 1.9.4
-------------------
** ADDED CONFIGURATION DIRECTIVES **
memoserv:modules added ms_ignore
chanserv:modules added cs_clone and cs_mode
nickserv:suspendexpire and nickserv:forbidexpire added
@@ -7,10 +8,16 @@ chanserv:suspendexpire and chanserv:forbidexpire added
module added cs_entrymsg
nickserv:modules added ns_ajoin
options:nomlock added
log:target added globops
nickserv:confirmemailchanges added
** MODIFIED CONFIGURATION DIRECTIVES **
operserv:notifications removed osglobal, osmode, oskick, osakill, ossnline, ossqline, osszline, osnoop, osjupe, getpass, setpass, forbid, drop
renamed nickserv:preregexpire to nickserv:unconfirmedexpire
** DELETED CONFIGURATION DIRECTIVES **
opertype:commands removed operserv/umode
operserv:modules removed os_umode
operserv:notifications removed osglobal, osmode, oskick, osakill, ossnline, ossqline, osszline, osnoop, osjupe, getpass, setpass, forbid, drop
log:target added globops
Anope Version 1.9.3
------------------
+4 -19
View File
@@ -5,15 +5,12 @@
class NickAlias;
class NickCore;
class NickRequest;
typedef unordered_map_namespace::unordered_map<Anope::string, NickAlias *, ci::hash, std::equal_to<ci::string> > nickalias_map;
typedef unordered_map_namespace::unordered_map<Anope::string, NickCore *, ci::hash, std::equal_to<ci::string> > nickcore_map;
typedef unordered_map_namespace::unordered_map<Anope::string, NickRequest *, ci::hash, std::equal_to<ci::string> > nickrequest_map;
extern CoreExport nickalias_map NickAliasList;
extern CoreExport nickcore_map NickCoreList;
extern CoreExport nickrequest_map NickRequestList;
/* NickServ nickname structures. */
@@ -85,6 +82,9 @@ enum NickCoreFlag
NI_AUTOOP,
/* This nickcore is forbidden, which means the nickalias for it is aswell */
NI_FORBIDDEN,
/* If set means the nick core does not have their email addrses confirmed.
*/
NI_UNCONFIRMED,
NI_END
};
@@ -92,22 +92,7 @@ enum NickCoreFlag
const Anope::string NickCoreFlagStrings[] = {
"BEGIN", "KILLPROTECT", "SECURE", "MSG", "MEMO_HARDMAX", "MEMO_SIGNON", "MEMO_RECEIVE",
"PRIVATE", "HIDE_EMAIL", "HIDE_MASK", "HIDE_QUIT", "KILL_QUICK", "KILL_IMMED",
"MEMO_MAIL", "HIDE_STATUS", "SUSPENDED", "AUTOOP", "FORBIDDEN", ""
};
class CoreExport NickRequest : public Extensible
{
public:
NickRequest(const Anope::string &nickname);
~NickRequest();
Anope::string nick;
Anope::string passcode;
Anope::string password;
Anope::string email;
time_t requested;
time_t lastmail; /* Unsaved */
"MEMO_MAIL", "HIDE_STATUS", "SUSPENDED", "AUTOOP", "FORBIDDEN", "UNCONFIRMED", ""
};
class NickCore;
+1 -1
View File
@@ -336,7 +336,7 @@ namespace Anope
* @param ... any number of parameters
* @return a Anope::string
*/
extern CoreExport string printf(const char *fmt, ...);
extern CoreExport string printf(const Anope::string &fmt, ...);
/** Return the last error, uses errno/GetLastError() to determin this
* @return An error message
+4 -2
View File
@@ -601,10 +601,12 @@ class CoreExport ServerConfig
time_t NSSuspendExpire;
/* How long before forbidden nicks expire */
time_t NSForbidExpire;
/* Time before NickRequests expire */
time_t NSRExpire;
/* Time before unconfirmed nicks expire */
time_t NSUnconfirmedExpire;
/* Force email when registering */
bool NSForceEmail;
/* Force users to validate new email addresses */
bool NSConfirmEmailChanges;
/* Max number of nicks in a group */
unsigned NSMaxAliases;
/* Max number of allowed strings on the access list */
-4
View File
@@ -232,8 +232,6 @@ E size_t strlcpy(char *, const char *, size_t);
#ifndef HAVE_STRLCAT
E size_t strlcat(char *, const char *, size_t);
#endif
E const char *merge_args(int argc, char **argv);
E const char *merge_args(int argc, const char **argv);
E time_t dotime(const Anope::string &s);
E Anope::string duration(NickCore *nc, time_t seconds);
@@ -277,7 +275,6 @@ E void SetDefaultMLock(ServerConfig *config);
/**** nickserv.c ****/
E NickRequest *findrequestnick(const Anope::string &nick);
E void get_aliases_stats(long &count, long &mem);
E void get_core_stats(long &count, long &mem);
E void change_core_display(NickCore *nc);
@@ -287,7 +284,6 @@ E int do_setmodes(User *u);
E void ns_init();
E int validate_user(User *u);
E void expire_nicks();
E void expire_requests();
E NickAlias *findnick(const Anope::string &nick);
E NickCore *findcore(const Anope::string &nick);
E bool is_on_access(const User *u, const NickCore *nc);
-1
View File
@@ -61,7 +61,6 @@
#define NICK_RECOVERED "User claiming your nick has been killed.\n" \
"\002%R%s RELEASE %s\002 to get it back before %s timeout."
#define NICK_REQUESTED "This nick has already been requested, please check your e-mail address for the pass code"
#define NICK_IS_PREREG "This nick is awaiting an e-mail verification code before completing registration."
#define NICK_CONFIRM_INVALID "Invalid passcode has been entered, please check the e-mail again, and retry"
#define CHAN_NOT_ALLOWED_TO_JOIN "You are not permitted to be on this channel."
#define CHAN_X_INVALID "Channel %s is not a valid channel."
-1
View File
@@ -3,7 +3,6 @@
#include "anope.h"
extern CoreExport bool Mail(User *u, NickRequest *nr, BotInfo *service, const Anope::string &subject, const Anope::string &message);
extern CoreExport bool Mail(User *u, NickCore *nc, BotInfo *service, const Anope::string &subject, const Anope::string &message);
extern CoreExport bool Mail(NickCore *nc, const Anope::string &subject, const Anope::string &message);
extern CoreExport bool MailValidate(const Anope::string &email);
+1 -25
View File
@@ -561,14 +561,6 @@ class CoreExport Module : public Extensible
*/
virtual EventReturn OnDatabaseReadMetadata(NickAlias *na, const Anope::string &key, const std::vector<Anope::string> &params) { return EVENT_CONTINUE; }
/** Called when nickrequest metadata is read from the database
* @param nr The nickrequest
* @parm key The metadata key
* @param params The params from the database
* @return EVENT_CONTINUE to let other modules decide, EVENT_STOP to stop processing
*/
virtual EventReturn OnDatabaseReadMetadata(NickRequest *nr, const Anope::string &key, const std::vector<Anope::string> &params) { return EVENT_CONTINUE; }
/** Called when botinfo metadata is read from the database
* @param bi The botinfo
* @param key The metadata key
@@ -597,12 +589,6 @@ class CoreExport Module : public Extensible
*/
virtual void OnDatabaseWriteMetadata(void (*WriteMetadata)(const Anope::string &, const Anope::string &), NickAlias *na) { }
/** Called when we are wrting metadata for a nickrequest
* @param WriteMetata A callback function used to insert the metadata
* @param nr The nick request
*/
virtual void OnDatabaseWriteMetadata(void (*WriteMetadata)(const Anope::string &, const Anope::string &), NickRequest *nr) { }
/** Called when we are writing metadata for a botinfo
* @param WriteMetata A callback function used to insert the metadata
* @param bi The botinfo
@@ -884,16 +870,6 @@ class CoreExport Module : public Extensible
*/
virtual void OnChangeCoreDisplay(NickCore *nc, const Anope::string &newdisplay) { }
/** called from ns_register.c, after the NickRequest have been created
* @param nr pointer to the NickRequest
*/
virtual void OnMakeNickRequest(NickRequest *nr) { }
/** called on delnickrequest()
* @param nr pointer to the NickRequest
*/
virtual void OnDelNickRequest(NickRequest *nr) { }
/** called from NickCore::ClearAccess()
* @param nc pointer to the NickCore
*/
@@ -1082,7 +1058,7 @@ enum Implementation
I_OnPreNickExpire, I_OnNickExpire, I_OnNickForbidden, I_OnNickGroup, I_OnNickLogout, I_OnNickIdentify, I_OnNickDrop,
I_OnNickRegister, I_OnNickSuspended, I_OnNickUnsuspended,
I_OnDelNick, I_OnDelCore, I_OnChangeCoreDisplay,
I_OnDelNickRequest, I_OnMakeNickRequest, I_OnNickClearAccess, I_OnNickAddAccess, I_OnNickEraseAccess,
I_OnNickClearAccess, I_OnNickAddAccess, I_OnNickEraseAccess,
I_OnNickInfo, I_OnFindNick, I_OnFindCore,
/* ChanServ */
-2
View File
@@ -448,7 +448,6 @@ template<typename T> inline T convertTo(const Anope::string &s, bool failIfLefto
class User;
class NickCore;
class NickAlias;
class NickRequest;
class BotInfo;
class ChannelInfo;
class Channel;
@@ -879,7 +878,6 @@ struct MailInfo
FILE *pipe;
User *sender;
NickCore *recipient;
NickRequest *recip;
};
/*************************************************************************/
+3 -5
View File
@@ -32,12 +32,10 @@ class CommandCSRegister : public Command
Channel *c = findchan(chan);
if (readonly)
{
source.Reply(_("Sorry, channel registration is temporarily disabled."));
return MOD_CONT;
}
if (chan[0] == '&')
else if (u->Account()->HasFlag(NI_UNCONFIRMED))
source.Reply(_("You must confirm your account before you can register a channel."));
else if (chan[0] == '&')
source.Reply(_("Local channels cannot be registered."));
else if (chan[0] != '#')
source.Reply(_(CHAN_SYMBOL_REQUIRED));
-43
View File
@@ -22,7 +22,6 @@ enum MDType
MD_NONE,
MD_NC,
MD_NA,
MD_NR,
MD_BI,
MD_CH
};
@@ -52,7 +51,6 @@ static void ReadDatabase(Module *m = NULL)
NickCore *nc = NULL;
NickAlias *na = NULL;
NickRequest *nr = NULL;
BotInfo *bi = NULL;
ChannelInfo *ci = NULL;
@@ -100,11 +98,6 @@ static void ReadDatabase(Module *m = NULL)
na = findnick(params[2]);
Type = MD_NA;
}
else if (params[0].equals_ci("NR"))
{
nr = findrequestnick(params[1]);
Type = MD_NR;
}
else if (params[0].equals_ci("BI"))
{
bi = findbot(params[1]);
@@ -149,20 +142,6 @@ static void ReadDatabase(Module *m = NULL)
Log() << "[db_plain]: " << ex.GetReason();
}
}
else if (Type == MD_NR && nr)
{
try
{
if (m)
m->OnDatabaseReadMetadata(nr, key, params);
else
FOREACH_RESULT(I_OnDatabaseReadMetadata, OnDatabaseReadMetadata(nr, key, params));
}
catch (const DatabaseException &ex)
{
Log() << "[db_plain]: " << ex.GetReason();
}
}
else if (Type == MD_BI && bi)
{
try
@@ -292,17 +271,6 @@ static void LoadNickAlias(const std::vector<Anope::string> &params)
Log(LOG_DEBUG_2) << "[db_plain}: Loaded nickalias for " << na->nick;
}
static void LoadNickRequest(const std::vector<Anope::string> &params)
{
NickRequest *nr = new NickRequest(params[0]);
nr->passcode = params[1];
nr->password = params[2];
nr->email = params[3];
nr->requested = params[4].is_pos_number_only() ? convertTo<time_t>(params[4]) : 0;
Log(LOG_DEBUG_2) << "[db_plain]: Loaded nickrequest for " << nr->nick;
}
static void LoadBotInfo(const std::vector<Anope::string> &params)
{
BotInfo *bi = findbot(params[0]);
@@ -480,8 +448,6 @@ class DBPlain : public Module
LoadNickCore(otherparams);
else if (key.equals_ci("NA"))
LoadNickAlias(otherparams);
else if (key.equals_ci("NR"))
LoadNickRequest(otherparams);
else if (key.equals_ci("BI"))
LoadBotInfo(otherparams);
else if (key.equals_ci("CH"))
@@ -765,15 +731,6 @@ class DBPlain : public Module
db_buffer << "VER 2" << endl;
for (nickrequest_map::const_iterator it = NickRequestList.begin(), it_end = NickRequestList.end(); it != it_end; ++it)
{
NickRequest *nr = it->second;
db_buffer << "NR " << nr->nick << " " << nr->passcode << " " << nr->password << " " << nr->email << " " << nr->requested << endl;
FOREACH_MOD(I_OnDatabaseWriteMetadata, OnDatabaseWriteMetadata(WriteMetadata, nr));
}
for (nickcore_map::const_iterator nit = NickCoreList.begin(), nit_end = NickCoreList.end(); nit != nit_end; ++nit)
{
NickCore *nc = nit->second;
+1 -24
View File
@@ -36,30 +36,7 @@ class CommandNSDrop : public Command
NickAlias *na = findnick((u->Account() && !nick.empty() ? nick : u->nick));
if (!na)
{
NickRequest *nr = findrequestnick(u->Account() && !nick.empty() ? nick : u->nick);
if (nr && u->Account() && u->Account()->IsServicesOper())
{
Log(LOG_ADMIN, u, this) << "to drop nickname " << nr->nick << " (email: " << nr->email << ")";
delete nr;
source.Reply(_("Nickname \002%s\002 has been dropped."), nick.c_str());
}
else if (nr && !nick.empty())
{
int res = enc_check_password(nick, nr->password);
if (res)
{
Log(LOG_COMMAND, u, this) << "to drop nick request " << nr->nick;
source.Reply(_("Nickname \002%s\002 has been dropped."), nr->nick.c_str());
delete nr;
}
else if (bad_password(u))
return MOD_STOP;
else
source.Reply(_(PASSWORD_INCORRECT));
}
else
source.Reply(_(NICK_NOT_REGISTERED));
source.Reply(_(NICK_NOT_REGISTERED));
return MOD_CONT;
}
+1 -10
View File
@@ -27,18 +27,9 @@ class CommandNSGetPass : public Command
const Anope::string &nick = params[0];
Anope::string tmp_pass;
NickAlias *na;
NickRequest *nr = NULL;
if (!(na = findnick(nick)))
{
if ((nr = findrequestnick(nick)))
{
Log(LOG_ADMIN, u, this) << "for " << nr->nick;
source.Reply(_("Passcode for %s is \002%s\002."), nick.c_str(), nr->passcode.c_str());
}
else
source.Reply(_(NICK_X_NOT_REGISTERED), nick.c_str());
}
source.Reply(_(NICK_X_NOT_REGISTERED), nick.c_str());
else if (na->HasFlag(NS_FORBIDDEN))
source.Reply(_(NICK_X_FORBIDDEN), na->nick.c_str());
else if (Config->NSSecureAdmins && na->nc->IsServicesOper())
+2 -7
View File
@@ -29,12 +29,6 @@ class CommandNSGroup : public Command
const Anope::string &nick = params[0];
Anope::string pass = params[1];
if (Config->NSEmailReg && findrequestnick(u->nick))
{
source.Reply(_(NICK_REQUESTED));
return MOD_CONT;
}
if (readonly)
{
source.Reply(_("Sorry, nickname grouping is temporarily disabled."));
@@ -121,7 +115,8 @@ class CommandNSGroup : public Command
u->Login(na->nc);
FOREACH_MOD(I_OnNickGroup, OnNickGroup(u, target));
ircdproto->SetAutoIdentificationToken(u);
u->SetMode(NickServ, UMODE_REGISTERED);
if (target->nc->HasFlag(NI_UNCONFIRMED) == false)
u->SetMode(NickServ, UMODE_REGISTERED);
Log(LOG_COMMAND, u, 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());
+11 -9
View File
@@ -31,13 +31,7 @@ class CommandNSIdentify : public Command
NickAlias *na = findnick(nick), *this_na = findnick(u->nick);
if (!na)
{
NickRequest *nr = findrequestnick(nick);
if (nr)
source.Reply(_(NICK_IS_PREREG));
else
source.Reply(_(NICK_NOT_REGISTERED));
}
source.Reply(_(NICK_NOT_REGISTERED));
else if (na->HasFlag(NS_FORBIDDEN))
source.Reply(_(NICK_X_FORBIDDEN), na->nick.c_str());
else if (na->nc->HasFlag(NI_SUSPENDED))
@@ -72,7 +66,7 @@ class CommandNSIdentify : public Command
ircdproto->SendAccountLogin(u, u->Account());
ircdproto->SetAutoIdentificationToken(u);
if (this_na && this_na->nc == na->nc)
if (this_na && this_na->nc == na->nc && this_na->nc->HasFlag(NI_UNCONFIRMED) == false)
u->SetMode(NickServ, UMODE_REGISTERED);
u->UpdateHost();
@@ -86,7 +80,7 @@ class CommandNSIdentify : public Command
FOREACH_MOD(I_OnNickIdentify, OnNickIdentify(u));
if (Config->NSForceEmail && u->Account() && u->Account()->email.empty())
if (Config->NSForceEmail && u->Account()->email.empty())
{
source.Reply(_("You must now supply an e-mail for your nick.\n"
"This e-mail will allow you to retrieve your password in\n"
@@ -96,6 +90,14 @@ class CommandNSIdentify : public Command
"any third-party person."), NickServ->nick.c_str());
}
if (u->Account()->HasFlag(NI_UNCONFIRMED))
{
source.Reply(_("Your email address is not confirmed. To confirm it, follow the instructions that were emailed to you when you registered."));
time_t time_registered = Anope::CurTime - na->time_registered;
if (Config->NSUnconfirmedExpire > time_registered)
source.Reply(_("Your account will expire, if not confirmed, in %s"), duration(u->Account(), Config->NSUnconfirmedExpire - time_registered).c_str());
}
check_memos(u);
}
}
+17 -16
View File
@@ -44,14 +44,7 @@ class CommandNSInfo : public Command
if (!na)
{
NickRequest *nr = findrequestnick(nick);
if (nr)
{
source.Reply(_(NICK_IS_PREREG));
if (has_auspex)
source.Reply(_(" E-mail address: %s"), nr->email.c_str());
}
else if (nickIsServices(nick, true))
if (nickIsServices(nick, true))
source.Reply(_("Nick \002%s\002 is part of this Network's Services."), nick.c_str());
else
source.Reply(_(NICK_X_NOT_REGISTERED), nick.c_str());
@@ -120,11 +113,11 @@ class CommandNSInfo : public Command
Anope::string optbuf;
CheckOptStr(optbuf, NI_KILLPROTECT, GetString(u->Account(), _("Protection")).c_str(), na->nc);
CheckOptStr(optbuf, NI_SECURE, GetString(u->Account(), _("Security")).c_str(), na->nc);
CheckOptStr(optbuf, NI_PRIVATE, GetString(u->Account(), _("Private")).c_str(), na->nc);
CheckOptStr(optbuf, NI_MSG, GetString(u->Account(), _("Message mode")).c_str(), na->nc);
CheckOptStr(optbuf, NI_AUTOOP, GetString(u->Account(), _("Auto-op")).c_str(), na->nc);
CheckOptStr(optbuf, NI_KILLPROTECT, _("Protection"), na->nc);
CheckOptStr(optbuf, NI_SECURE, _("Security"), na->nc);
CheckOptStr(optbuf, NI_PRIVATE, _("Private"), na->nc);
CheckOptStr(optbuf, NI_MSG, _("Message mode"), na->nc);
CheckOptStr(optbuf, NI_AUTOOP, _("Auto-op"), na->nc);
source.Reply(_(NICK_INFO_OPTIONS), optbuf.empty() ? _("None") : optbuf.c_str());
@@ -136,13 +129,21 @@ class CommandNSInfo : public Command
source.Reply(_("This nickname is currently suspended"));
}
if (na->HasFlag(NS_NO_EXPIRE))
source.Reply(_("This nickname will not expire."));
if (na->nc->HasFlag(NI_UNCONFIRMED) == false)
{
if (na->HasFlag(NS_NO_EXPIRE))
source.Reply(_("This nickname will not expire."));
else
source.Reply(_("Expires on: %s"), do_strftime(na->last_seen + Config->NSExpire).c_str());
}
else
source.Reply(_("Expires on: %s"), do_strftime(na->last_seen + Config->NSExpire).c_str());
source.Reply(_("Expires on: %s"), do_strftime(na->time_registered + Config->NSUnconfirmedExpire).c_str());
}
FOREACH_MOD(I_OnNickInfo, OnNickInfo(source, na, show_hidden));
if (na->nc->HasFlag(NI_UNCONFIRMED))
source.Reply(_("This nickname is unconfirmed."));
}
return MOD_CONT;
}
+40 -54
View File
@@ -97,67 +97,53 @@ class CommandNSList : public Command
mync = u->Account();
source.Reply(_(LIST_HEADER), pattern.c_str());
if (!unconfirmed)
for (nickalias_map::const_iterator it = NickAliasList.begin(), it_end = NickAliasList.end(); it != it_end; ++it)
{
for (nickalias_map::const_iterator it = NickAliasList.begin(), it_end = NickAliasList.end(); it != it_end; ++it)
NickAlias *na = it->second;
/* Don't show private and forbidden nicks to non-services admins. */
if (na->HasFlag(NS_FORBIDDEN) && !is_servadmin)
continue;
else if (na->nc->HasFlag(NI_PRIVATE) && !is_servadmin && na->nc != mync)
continue;
else if (forbidden && !na->HasFlag(NS_FORBIDDEN))
continue;
else if (nsnoexpire && !na->HasFlag(NS_NO_EXPIRE))
continue;
else if (suspended && !na->nc->HasFlag(NI_SUSPENDED))
continue;
else if (unconfirmed && na->nc->HasFlag(NI_UNCONFIRMED))
continue;
/* We no longer compare the pattern against the output buffer.
* Instead we build a nice nick!user@host buffer to compare.
* The output is then generated separately. -TheShadow */
snprintf(buf, sizeof(buf), "%s!%s", na->nick.c_str(), !na->last_usermask.empty() && !na->HasFlag(NS_FORBIDDEN) ? na->last_usermask.c_str() : "*@*");
if (na->nick.equals_ci(pattern) || Anope::Match(buf, pattern))
{
NickAlias *na = it->second;
/* Don't show private and forbidden nicks to non-services admins. */
if (na->HasFlag(NS_FORBIDDEN) && !is_servadmin)
continue;
if (na->nc->HasFlag(NI_PRIVATE) && !is_servadmin && na->nc != mync)
continue;
if (forbidden && !na->HasFlag(NS_FORBIDDEN))
continue;
else if (nsnoexpire && !na->HasFlag(NS_NO_EXPIRE))
continue;
else if (suspended && !na->nc->HasFlag(NI_SUSPENDED))
continue;
/* We no longer compare the pattern against the output buffer.
* Instead we build a nice nick!user@host buffer to compare.
* The output is then generated separately. -TheShadow */
snprintf(buf, sizeof(buf), "%s!%s", na->nick.c_str(), !na->last_usermask.empty() && !na->HasFlag(NS_FORBIDDEN) ? na->last_usermask.c_str() : "*@*");
if (na->nick.equals_ci(pattern) || Anope::Match(buf, pattern))
if (((count + 1 >= from && count + 1 <= to) || (!from && !to)) && ++nnicks <= Config->NSListMax)
{
if (((count + 1 >= from && count + 1 <= to) || (!from && !to)) && ++nnicks <= Config->NSListMax)
{
if (is_servadmin && na->HasFlag(NS_NO_EXPIRE))
noexpire_char = '!';
else
noexpire_char = ' ';
if (na->nc->HasFlag(NI_HIDE_MASK) && !is_servadmin && na->nc != mync)
snprintf(buf, sizeof(buf), "%-20s [Hostname Hidden]", na->nick.c_str());
else if (na->HasFlag(NS_FORBIDDEN))
snprintf(buf, sizeof(buf), "%-20s [Forbidden]", na->nick.c_str());
else if (na->nc->HasFlag(NI_SUSPENDED))
snprintf(buf, sizeof(buf), "%-20s [Suspended]", na->nick.c_str());
else
snprintf(buf, sizeof(buf), "%-20s %s", na->nick.c_str(), na->last_usermask.c_str());
source.Reply(" %c%s", noexpire_char, buf);
}
++count;
}
}
}
if (unconfirmed || is_servadmin)
{
noexpire_char = ' ';
for (nickrequest_map::const_iterator it = NickRequestList.begin(), it_end = NickRequestList.end(); it != it_end; ++it)
{
NickRequest *nr = it->second;
snprintf(buf, sizeof(buf), "%s!*@*", nr->nick.c_str());
if ((nr->nick.equals_ci(pattern) || Anope::Match(buf, pattern)) && ++nnicks <= Config->NSListMax)
{
snprintf(buf, sizeof(buf), "%-20s [UNCONFIRMED]", nr->nick.c_str());
if (is_servadmin && na->HasFlag(NS_NO_EXPIRE))
noexpire_char = '!';
else
noexpire_char = ' ';
if (na->nc->HasFlag(NI_HIDE_MASK) && !is_servadmin && na->nc != mync)
snprintf(buf, sizeof(buf), "%-20s [Hostname Hidden]", na->nick.c_str());
else if (na->HasFlag(NS_FORBIDDEN))
snprintf(buf, sizeof(buf), "%-20s [Forbidden]", na->nick.c_str());
else if (na->nc->HasFlag(NI_SUSPENDED))
snprintf(buf, sizeof(buf), "%-20s [Suspended]", na->nick.c_str());
else if (na->nc->HasFlag(NI_UNCONFIRMED))
snprintf(buf, sizeof(buf), "%-20s [Unconfirmed]", na->nick.c_str());
else
snprintf(buf, sizeof(buf), "%-20s %s", na->nick.c_str(), na->last_usermask.c_str());
source.Reply(" %c%s", noexpire_char, buf);
}
++count;
}
}
source.Reply(_("End of list - %d/%d matches shown."), nnicks > Config->NSListMax ? Config->NSListMax : nnicks, nnicks);
return MOD_CONT;
}
+134 -197
View File
@@ -13,130 +13,52 @@
#include "module.h"
static bool SendRegmail(User *u, NickRequest *nr);
static bool SendRegmail(User *u, NickAlias *na);
class CommandNSConfirm : public Command
{
protected:
CommandReturn ActuallyConfirmNick(CommandSource &source, NickRequest *nr, bool force)
{
User *u = source.u;
NickAlias *na = new NickAlias(nr->nick, new NickCore(nr->nick));
Anope::string tmp_pass;
na->nc->pass = nr->password;
if (force)
{
na->last_usermask = "*@*";
na->last_realname = "unknown";
}
else
{
Anope::string last_usermask = u->GetIdent() + "@" + u->GetDisplayedHost();
na->last_usermask = last_usermask;
na->last_realname = u->realname;
if (Config->NSAddAccessOnReg)
na->nc->AddAccess(create_mask(u));
}
if (!nr->email.empty())
na->nc->email = nr->email;
if (!force)
{
u->Login(na->nc);
Log(LOG_COMMAND, u, this) << "to register " << nr->nick << " (email: " << (!nr->email.empty() ? nr->email : "none") << ")";
if (Config->NSAddAccessOnReg)
source.Reply(_("Nickname \002%s\002 registered under your account: %s"), u->nick.c_str(), na->nc->GetAccess(0).c_str());
else
source.Reply(_("Nickname \002%s\002 registered."), u->nick.c_str());
delete nr;
ircdproto->SendAccountLogin(u, u->Account());
ircdproto->SetAutoIdentificationToken(u);
if (enc_decrypt(na->nc->pass, tmp_pass) == 1)
source.Reply(_("Your password is \002%s\002 - remember this for later use."), tmp_pass.c_str());
u->lastnickreg = Anope::CurTime;
}
else
{
Log(LOG_COMMAND, u, this) << "to confirm " << nr->nick << " (email: " << (!nr->email.empty() ? nr->email : "none") << ")";
source.Reply(_("Nickname \002%s\002 confirmed"), nr->nick.c_str());
User *user = finduser(nr->nick);
/* Delrequest must be called before validate_user */
delete nr;
if (user)
validate_user(user);
}
FOREACH_MOD(I_OnNickRegister, OnNickRegister(na));
return MOD_CONT;
}
CommandReturn DoConfirm(CommandSource &source, const std::vector<Anope::string> &params)
{
User *u = source.u;
Anope::string passcode = !params.empty() ? params[0] : "";
NickRequest *nr = findrequestnick(u->nick);
if (Config->NSEmailReg)
{
if (passcode.empty())
{
this->OnSyntaxError(source, "");
return MOD_CONT;
}
if (!nr)
{
if (u->Account() && u->Account()->HasPriv("nickserv/confirm"))
{
/* If an admin, their nick is obviously already regged, so look at the passcode to get the nick
of the user they are trying to validate, and push that user through regardless of passcode */
nr = findrequestnick(passcode);
if (nr)
{
ActuallyConfirmNick(source, nr, true);
return MOD_CONT;
}
}
source.Reply(_("Registration step 1 may have expired, please use \"%R%s register <password> <email>\" first."), Config->s_NickServ.c_str());
return MOD_CONT;
}
if (!nr->passcode.equals_cs(passcode))
{
source.Reply(_(NICK_CONFIRM_INVALID));
return MOD_CONT;
}
}
if (!nr)
{
source.Reply(_("Sorry, registration failed."));
return MOD_CONT;
}
ActuallyConfirmNick(source, nr, false);
return MOD_CONT;
}
public:
CommandNSConfirm(const Anope::string &cmdn, int min, int max) : Command(cmdn, min, max)
CommandNSConfirm() : Command("CONFIRM", 1, 2)
{
this->SetFlag(CFLAG_ALLOW_UNREGISTERED);
this->SetDesc("Confirm a nickserv auth code");
this->SetDesc("Confirm an auth code");
}
CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> &params)
{
return this->DoConfirm(source, params);
User *u = source.u;
const Anope::string &passcode = params[0];
if (u->Account() && u->Account()->HasPriv("nickserv/confirm"))
{
NickAlias *na = findnick(passcode);
if (na == NULL)
source.Reply(_(NICK_X_NOT_REGISTERED), passcode.c_str());
else if (na->nc->HasFlag(NI_UNCONFIRMED) == false)
source.Reply(_("Nick \002%s\002 is already confirmed."), na->nick.c_str());
{
na->nc->UnsetFlag(NI_UNCONFIRMED);
Log(LOG_ADMIN, u, this) << "to confirm nick " << na->nick << " (" << na->nc->display << ")";
source.Reply(_("Nick \002%s\002 has been confirmed."), na->nick.c_str());
}
}
else if (u->Account())
{
Anope::string code;
if (u->Account()->GetExtRegular<Anope::string>("ns_register_passcode", code) && code == passcode)
{
u->Account()->Shrink("ns_register_passcode");
Log(LOG_COMMAND, u, this) << "to confirm their email";
source.Reply(_("Your email address of \002%s\002 has been confirmed."), u->Account()->email.c_str());
u->Account()->UnsetFlag(NI_UNCONFIRMED);
}
else
source.Reply(_("Invalid passcode."));
}
else
source.Reply(_("Invalid passcode."));
return MOD_CONT;
}
bool OnHelp(CommandSource &source, const Anope::string &subcommand)
@@ -144,16 +66,14 @@ class CommandNSConfirm : public Command
User *u = source.u;
source.Reply(_("Syntax: \002CONFIRM \037passcode\037\002\n"
" \n"
"This is the second step of nickname registration process.\n"
"You must perform this command in order to get your nickname\n"
"registered with %s. The passcode (or called auth code also)\n"
"is sent to your e-mail address in the first step of the\n"
"registration process. For more information about the first\n"
"stage of the registration process, type: \002%R%s HELP REGISTER\002\n"
"This command is used by several commands as a way to confirm\n"
"changes made to your account.\n"
" \n"
"This is most commonly used to confirm your email address once\n"
"you register or change it.\n"
" \n"
"This is also used after the RESETPASS command has been used to\n"
"force identify you to your nick so you may change your password."),
NickServ->nick.c_str());
"force identify you to your nick so you may change your password."));
if (u->Account() && u->Account()->HasPriv("nickserv/confirm"))
source.Reply(_("Additionally, Services Operators with the \037nickserv/confirm\037 permission can\n"
"replace \037passcode\037 with a users nick to force validate them."));
@@ -166,10 +86,10 @@ class CommandNSConfirm : public Command
}
};
class CommandNSRegister : public CommandNSConfirm
class CommandNSRegister : public Command
{
public:
CommandNSRegister() : CommandNSConfirm("REGISTER", 1, 2)
CommandNSRegister() : Command("REGISTER", 1, 2)
{
this->SetFlag(CFLAG_ALLOW_UNREGISTERED);
this->SetDesc("Register a nickname");
@@ -178,22 +98,11 @@ class CommandNSRegister : public CommandNSConfirm
CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> &params)
{
User *u = source.u;
NickRequest *nr = NULL, *anr = NULL;
NickAlias *na;
size_t prefixlen = Config->NSGuestNickPrefix.length();
size_t nicklen = u->nick.length();
Anope::string pass = params[0];
Anope::string email = params.size() > 1 ? params[1] : "";
Anope::string passcode;
int idx, min = 1, max = 62;
int chars[] = {
' ', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y',
'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y',
'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
};
std::list<std::pair<Anope::string, Anope::string> >::iterator it, it_end;
if (readonly)
{
@@ -207,12 +116,6 @@ class CommandNSRegister : public CommandNSConfirm
return MOD_CONT;
}
if ((anr = findrequestnick(u->nick)))
{
source.Reply(_(NICK_REQUESTED));
return MOD_CONT;
}
/* Prevent "Guest" nicks from being registered. -TheShadow */
/* Guest nick can now have a series of between 1 and 7 digits.
@@ -231,7 +134,7 @@ class CommandNSRegister : public CommandNSConfirm
}
if (Config->RestrictOperNicks)
for (it = Config->Opers.begin(), it_end = Config->Opers.end(); it != it_end; ++it)
for (std::list<std::pair<Anope::string, Anope::string> >::iterator it = Config->Opers.begin(), it_end = Config->Opers.end(); it != it_end; ++it)
{
Anope::string nick = it->first;
@@ -265,38 +168,46 @@ class CommandNSRegister : public CommandNSConfirm
source.Reply(_(MAIL_X_INVALID), email.c_str());
else
{
for (idx = 0; idx < 9; ++idx)
passcode += chars[1 + static_cast<int>((static_cast<float>(max - min)) * getrandom16() / 65536.0) + min];
nr = new NickRequest(u->nick);
nr->passcode = passcode;
enc_encrypt(pass, nr->password);
na = new NickAlias(u->nick, new NickCore(u->nick));
enc_encrypt(pass, na->nc->pass);
if (!email.empty())
nr->email = email;
nr->requested = Anope::CurTime;
FOREACH_MOD(I_OnMakeNickRequest, OnMakeNickRequest(nr));
na->nc->email = email;
Anope::string last_usermask = u->GetIdent() + "@" + u->GetDisplayedHost();
na->last_usermask = last_usermask;
na->last_realname = u->realname;
if (Config->NSAddAccessOnReg)
na->nc->AddAccess(create_mask(u));
u->Login(na->nc);
Log(LOG_COMMAND, u, this) << "to register " << na->nick << " (email: " << (!na->nc->email.empty() ? na->nc->email : "none") << ")";
FOREACH_MOD(I_OnNickRegister, OnNickRegister(na));
if (Config->NSAddAccessOnReg)
source.Reply(_("Nickname \002%s\002 registered under your account: %s"), u->nick.c_str(), na->nc->GetAccess(0).c_str());
else
source.Reply(_("Nickname \002%s\002 registered."), u->nick.c_str());
Anope::string tmp_pass;
if (enc_decrypt(na->nc->pass, tmp_pass) == 1)
source.Reply(_("Your password is \002%s\002 - remember this for later use."), tmp_pass.c_str());
if (Config->NSEmailReg)
{
if (SendRegmail(u, nr))
na->nc->SetFlag(NI_UNCONFIRMED);
if (SendRegmail(u, na))
{
source.Reply(_("A passcode has been sent to %s, please type %R%s confirm <passcode> to complete registration.\n"
"If you need to cancel your registration, use \"%R%s drop <password>\"."),
email.c_str(), Config->s_NickServ.c_str(), Config->s_NickServ.c_str());
source.Reply(_("A passcode has been sent to %s, please type %R%s confirm <passcode> to confirm your email address."), email.c_str(), NickServ->nick.c_str());
source.Reply(_("If you do not confirm your email address within %s your account will expire."), duration(na->nc, Config->NSUnconfirmedExpire).c_str());
}
}
Log(LOG_COMMAND, u, this) << "send registration verification code to " << nr->email;
}
else
{
Log(LOG_COMMAND, u, this) << "unable to send registration verification mail";
source.Reply(_("Nick NOT registered, please try again later."));
delete nr;
return MOD_CONT;
}
}
else
{
std::vector<Anope::string> empty_params;
return this->DoConfirm(source, empty_params);
}
ircdproto->SendAccountLogin(u, u->Account());
ircdproto->SetAutoIdentificationToken(u);
u->lastnickreg = Anope::CurTime;
}
return MOD_CONT;
@@ -353,47 +264,54 @@ class CommandNSResend : public Command
public:
CommandNSResend() : Command("RESEND", 0, 0)
{
this->SetFlag(CFLAG_ALLOW_UNREGISTERED);
this->SetDesc("Resend a nickserv auth code");
}
CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> &params)
{
if (!Config->NSEmailReg)
return MOD_CONT;
User *u = source.u;
NickRequest *nr = NULL;
if (Config->NSEmailReg)
NickAlias *na = findnick(u->nick);
if (na == NULL)
source.Reply(_(NICK_NOT_REGISTERED));
else if (na->nc != u->Account() || u->Account()->HasFlag(NI_UNCONFIRMED) == false)
source.Reply(_("Your account is already confirmed."));
else
{
if ((nr = findrequestnick(u->nick)))
if (Anope::CurTime < u->Account()->lastmail + Config->NSResendDelay)
source.Reply(_("Cannot send mail now; please retry a little later."));
else if (!SendRegmail(u, na))
{
if (Anope::CurTime < nr->lastmail + Config->NSResendDelay)
{
source.Reply(_("Cannot send mail now; please retry a little later."));
return MOD_CONT;
}
if (!SendRegmail(u, nr))
{
nr->lastmail = Anope::CurTime;
source.Reply(_("Your passcode has been re-sent to %s."), nr->email.c_str());
Log(LOG_COMMAND, u, this) << "resend registration verification code for " << nr->nick;
}
else
{
Log(LOG_COMMAND, u, this) << "unable to resend registration verification code for " << nr->nick;
return MOD_CONT;
}
na->nc->lastmail = Anope::CurTime;
source.Reply(_("Your passcode has been re-sent to %s."), na->nc->email.c_str());
Log(LOG_COMMAND, u, this) << "to resend registration verification code";
}
else
Log() << "Unable to resend registration verification code for " << u->nick;
}
return MOD_CONT;
}
bool OnHelp(CommandSource &source, const Anope::string &subcommand)
{
if (!Config->NSEmailReg)
return false;
source.Reply(_("Syntax: \002RESEND\002\n"
" \n"
"This command will re-send the auth code (also called passcode)\n"
"to the e-mail address of the user whom is performing it."));
return true;
}
void OnServHelp(CommandSource &source)
{
if (Config->NSEmailReg)
source.Reply(_("Resend the registration passcode"));
}
};
class NSRegister : public Module
@@ -403,7 +321,7 @@ class NSRegister : public Module
CommandNSResend commandnsrsend;
public:
NSRegister(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator), commandnsconfirm("CONFIRM", 1, 1)
NSRegister(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator)
{
this->SetAuthor("Anope");
this->SetType(CORE);
@@ -414,21 +332,40 @@ class NSRegister : public Module
}
};
static bool SendRegmail(User *u, NickRequest *nr)
static bool SendRegmail(User *u, NickAlias *na)
{
char subject[BUFSIZE], message[BUFSIZE];
Anope::string code;
if (na->nc->GetExtRegular<Anope::string>("ns_register_passcode", code) == false)
{
int chars[] = {
' ', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y',
'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y',
'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
};
int idx, min = 1, max = 62;
for (idx = 0; idx < 9; ++idx)
code += chars[1 + static_cast<int>((static_cast<float>(max - min)) * getrandom16() / 65536.0) + min];
na->nc->Extend("ns_register_passcode", new ExtensibleItemRegular<Anope::string>(code));
}
snprintf(subject, sizeof(subject), GetString(NULL, "Nickname Registration (%s)").c_str(), nr->nick.c_str());
snprintf(message, sizeof(message), GetString(NULL, "Hi,\n"
Anope::string subject = Anope::printf(_("Nickname Registration (%s)"), na->nick.c_str());
Anope::string message = Anope::printf(_("Hi,\n"
" \n"
"You have requested to register the nickname %s on %s.\n"
"Please type \" %R%s confirm %s \" to complete registration.\n"
" \n"
"If you don't know why this mail was sent to you, please ignore it silently.\n"
" \n"
"%s administrators.").c_str(), nr->nick.c_str(), Config->NetworkName.c_str(), Config->s_NickServ.c_str(), nr->passcode.c_str(), Config->NetworkName.c_str());
"%s administrators."), na->nick.c_str(), Config->NetworkName.c_str(), Config->s_NickServ.c_str(), code.c_str(), Config->NetworkName.c_str());
return Mail(u, nr, NickServ, subject, message);
if (Config->UseStrictPrivMsg)
message = message.replace_all_cs("%R", "/");
else
message = message.replace_all_cs("%R", "/msg ");
return Mail(u, na->nc, NickServ, subject, message);
}
MODULE_INIT(NSRegister)
+25 -26
View File
@@ -31,7 +31,7 @@ class CommandNSResetPass : public Command
if (Config->RestrictMail && (!u->Account() || !u->Account()->HasCommand("nickserv/resetpass")))
source.Reply(_(ACCESS_DENIED));
if (!(na = findnick(params[0])))
else if (!(na = findnick(params[0])))
source.Reply(_(NICK_X_NOT_REGISTERED), params[0].c_str());
else if (na->HasFlag(NS_FORBIDDEN))
source.Reply(_(NICK_X_FORBIDDEN), na->nick.c_str());
@@ -82,36 +82,40 @@ class NSResetPass : public Module
EventReturn OnPreCommand(CommandSource &source, Command *command, const std::vector<Anope::string> &params)
{
User *u = source.u;
BotInfo *service = source.owner;
if (service == NickServ && command->name.equals_ci("CONFIRM") && !params.empty())
if (command->service == NickServ && command->name.equals_ci("CONFIRM") && params.size() > 1)
{
NickAlias *na = findnick(source.u->nick);
NickAlias *na = findnick(params[0]);
time_t t;
Anope::string c;
if (na && na->nc->GetExtRegular("ns_resetpass_code", c) && na->nc->GetExtRegular("ns_resetpass_time", t))
{
const Anope::string &passcode = params[1];
if (t < Anope::CurTime - 3600)
{
na->nc->Shrink("ns_resetpass_code");
na->nc->Shrink("ns_resetpass_time");
source.Reply(_("Your password reset request has expired."));
return EVENT_STOP;
}
Anope::string passcode = params[0];
if (passcode.equals_cs(c))
else if (passcode.equals_cs(c))
{
na->nc->Shrink("ns_resetpass_code");
na->nc->Shrink("ns_resetpass_time");
u->UpdateHost();
na->last_realname = u->realname;
na->last_seen = Anope::CurTime;
NickAlias *this_na = findnick(u->nick);
if (this_na && this_na == na)
{
u->UpdateHost();
na->last_realname = u->realname;
na->last_seen = Anope::CurTime;
u->SetMode(NickServ, UMODE_REGISTERED);
}
u->Login(na->nc);
ircdproto->SendAccountLogin(u, u->Account());
ircdproto->SetAutoIdentificationToken(u);
u->SetMode(NickServ, UMODE_REGISTERED);
na->nc->UnsetFlag(NI_UNCONFIRMED);
FOREACH_MOD(I_OnNickIdentify, OnNickIdentify(u));
Log(LOG_COMMAND, u, &commandnsresetpass) << "confirmed RESETPASS to forcefully identify to " << na->nick;
@@ -124,11 +128,7 @@ class NSResetPass : public Module
check_memos(u);
}
else
{
Log(LOG_COMMAND, u, &commandnsresetpass) << "invalid confirm passcode for " << na->nick;
source.Reply(_(NICK_CONFIRM_INVALID));
bad_password(u);
}
return EVENT_CONTINUE;
return EVENT_STOP;
}
@@ -140,10 +140,6 @@ class NSResetPass : public Module
static bool SendResetEmail(User *u, NickAlias *na)
{
char subject[BUFSIZE], message[BUFSIZE];
snprintf(subject, sizeof(subject), GetString(na->nc, _("Reset password request for %s")).c_str(), na->nick.c_str());
int min = 1, max = 62;
int chars[] = {
' ', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
@@ -158,18 +154,21 @@ static bool SendResetEmail(User *u, NickAlias *na)
for (idx = 0; idx < 20; ++idx)
passcode += chars[1 + static_cast<int>((static_cast<float>(max - min)) * getrandom16() / 65536.0) + min];
snprintf(message, sizeof(message), GetString(na->nc,
Anope::string subject = Anope::printf(GetString(na->nc, "Reset password request for %s"), na->nick.c_str());
Anope::string message = Anope::printf(GetString(na->nc,
"Hi,\n"
" \n"
"You have requested to have the password for %s reset.\n"
"To reset your password, type \002%R%s CONFIRM %s\002\n"
"To reset your password, type %R%s CONFIRM %s %s\n"
" \n"
"If you don't know why this mail was sent to you, please ignore it silently.\n"
" \n"
"%s administrators.").c_str(), na->nick.c_str(), Config->s_NickServ.c_str(), passcode.c_str(), Config->NetworkName.c_str());
"%s administrators."), na->nick.c_str(), Config->s_NickServ.c_str(), na->nick.c_str(), passcode.c_str(), Config->NetworkName.c_str());
na->nc->Shrink("ns_resetpass_code");
na->nc->Shrink("ns_resetpass_time");
if (Config->UseStrictPrivMsg)
message = message.replace_all_cs("%R", "/");
else
message = message.replace_all_cs("%R", "/msg ");
na->nc->Extend("ns_resetpass_code", new ExtensibleItemRegular<Anope::string>(passcode));
na->nc->Extend("ns_resetpass_time", new ExtensibleItemRegular<time_t>(Anope::CurTime));
+75 -5
View File
@@ -13,6 +13,39 @@
#include "module.h"
static bool SendConfirmMail(User *u)
{
int chars[] = {
' ', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y',
'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y',
'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
};
int idx, min = 1, max = 62;
Anope::string code;
for (idx = 0; idx < 9; ++idx)
code += chars[1 + static_cast<int>((static_cast<float>(max - min)) * getrandom16() / 65536.0) + min];
u->Account()->Extend("ns_set_email_passcode", new ExtensibleItemRegular<Anope::string>(code));
Anope::string subject = _("Email confirmation");
Anope::string message = Anope::printf(_("Hi,\n"
" \n"
"You have requested to change your email address to %s.\n"
"Please type \" %R%s confirm %s \" to confirm this change.\n"
" \n"
"If you don't know why this mail was sent to you, please ignore it silently.\n"
" \n"
"%s administrators."), u->Account()->email.c_str(), Config->s_NickServ.c_str(), code.c_str(), Config->NetworkName.c_str());
if (Config->UseStrictPrivMsg)
message = message.replace_all_cs("%R", "/");
else
message = message.replace_all_cs("%R", "/msg ");
return Mail(u, u->Account(), NickServ, subject, message);
}
class CommandNSSetEmail : public Command
{
public:
@@ -47,15 +80,27 @@ class CommandNSSetEmail : public Command
return MOD_CONT;
}
if (!param.empty())
if (!param.empty() && Config->NSConfirmEmailChanges && !u->Account()->IsServicesOper())
{
nc->email = param;
source.Reply(_("E-mail address for \002%s\002 changed to \002%s\002."), nc->display.c_str(), param.c_str());
u->Account()->Extend("ns_set_email", new ExtensibleItemRegular<Anope::string>(param));
Anope::string old = u->Account()->email;
u->Account()->email = param;
if (SendConfirmMail(u))
source.Reply(_("A confirmation email has been sent to \002%s\002. Follow the instructions in it to change your email address."), param.c_str());
u->Account()->email = old;
}
else
{
nc->email.clear();
source.Reply(_("E-mail address for \002%s\002 unset."), nc->display.c_str());
if (!param.empty())
{
nc->email = param;
source.Reply(_("E-mail address for \002%s\002 changed to \002%s\002."), nc->display.c_str(), param.c_str());
}
else
{
nc->email.clear();
source.Reply(_("E-mail address for \002%s\002 unset."), nc->display.c_str());
}
}
return MOD_CONT;
@@ -99,6 +144,8 @@ class NSSetEmail : public Module
this->SetAuthor("Anope");
this->SetType(CORE);
ModuleManager::Attach(I_OnPreCommand, this);
Command *c = FindCommand(NickServ, "SET");
if (c)
c->AddSubcommand(this, &commandnssetemail);
@@ -118,6 +165,29 @@ class NSSetEmail : public Module
if (c)
c->DelSubcommand(&commandnssasetemail);
}
EventReturn OnPreCommand(CommandSource &source, Command *command, const std::vector<Anope::string> &params)
{
User *u = source.u;
if (command->service == NickServ && command->name.equals_ci("CONFIRM") && !params.empty() && u->IsIdentified())
{
Anope::string new_email, passcode;
if (u->Account()->GetExtRegular("ns_set_email", new_email) && u->Account()->GetExtRegular("ns_set_email_passcode", passcode))
{
if (params[0] == passcode)
{
u->Account()->email = new_email;
Log(LOG_COMMAND, u, command) << "to confirm their email address change to " << u->Account()->email;
source.Reply(_("Your email address has been changed to \002%s\002."), u->Account()->email.c_str());
u->Account()->Shrink("ns_set_email");
u->Account()->Shrink("ns_set_email_passcode");
return EVENT_STOP;
}
}
}
return EVENT_CONTINUE;
}
};
MODULE_INIT(NSSetEmail)
+3 -28
View File
@@ -217,8 +217,8 @@ class DBMySQL : public Module
I_OnSaveDatabase, I_OnPostCommand,
/* NickServ */
I_OnNickAddAccess, I_OnNickEraseAccess, I_OnNickClearAccess,
I_OnDelCore, I_OnNickForbidden, I_OnNickGroup, I_OnMakeNickRequest,
I_OnDelNickRequest, I_OnNickRegister, I_OnChangeCoreDisplay,
I_OnDelCore, I_OnNickForbidden, I_OnNickGroup,
I_OnNickRegister, I_OnChangeCoreDisplay,
I_OnNickSuspended, I_OnDelNick,
/* ChanServ */
I_OnAccessAdd, I_OnAccessDel, I_OnAccessChange, I_OnAccessClear, I_OnLevelChange,
@@ -236,7 +236,7 @@ class DBMySQL : public Module
/* HostServ */
I_OnSetVhost, I_OnDeleteVhost
};
ModuleManager::Attach(i, this, 42);
ModuleManager::Attach(i, this, 40);
}
EventReturn OnLoadDatabase()
@@ -588,16 +588,6 @@ class DBMySQL : public Module
FOREACH_RESULT(I_OnDatabaseReadMetadata, OnDatabaseReadMetadata(ci, ci->name, Params));
}
r = SQL->RunQuery("SELECT * FROM `anope_ns_request`");
for (int i = 0; i < r.Rows(); ++i)
{
NickRequest *nr = new NickRequest(r.Get(i, "nick"));
nr->password = r.Get(i, "passcode");
nr->password = r.Get(i, "password");
nr->email = r.Get(i, "email");
nr->requested = r.Get(i, "requested").is_pos_number_only() ? convertTo<time_t>(r.Get(i, "requested")) : Anope::CurTime;
}
r = SQL->RunQuery("SELECT * FROM `anope_ms_info`");
for (int i = 0; i < r.Rows(); ++i)
{
@@ -947,16 +937,6 @@ class DBMySQL : public Module
OnNickRegister(findnick(u->nick));
}
void OnMakeNickRequest(NickRequest *nr)
{
this->RunQuery("INSERT INTO `anope_ns_request` (nick, passcode, password, email, requested) VALUES('" + this->Escape(nr->nick) + "', '" + this->Escape(nr->passcode) + "', '" + this->Escape(nr->password) + "', '" + this->Escape(nr->email) + "', " + stringify(nr->requested) + ")");
}
void OnDelNickRequest(NickRequest *nr)
{
this->RunQuery("DELETE FROM `anope_ns_request` WHERE `nick` = '" + this->Escape(nr->nick) + "'");
}
void InsertAlias(NickAlias *na)
{
this->RunQuery("INSERT INTO `anope_ns_alias` (nick, last_quit, last_realname, last_usermask, time_registered, last_seen, flags, display) VALUES('" +
@@ -1369,11 +1349,6 @@ static void SaveDatabases()
}
}
me->RunQuery("TRUNCATE TABLE `anope_ns_request`");
for (nickrequest_map::const_iterator it = NickRequestList.begin(), it_end = NickRequestList.end(); it != it_end; ++it)
me->OnMakeNickRequest(it->second);
if (SGLine)
for (unsigned i = 0, end = SGLine->GetCount(); i < end; ++i)
me->OnAddAkill(NULL, SGLine->GetEntry(i));
+5 -1
View File
@@ -222,7 +222,10 @@ class ModuleLDAP : public Module, public Pipe
~ModuleLDAP()
{
for (std::map<Anope::string, LDAPService *>::iterator it = this->LDAPServices.begin(); it != this->LDAPServices.end(); ++it)
{
it->second->SetExitState();
it->second->Wakeup();
}
LDAPServices.clear();
}
@@ -239,7 +242,7 @@ class ModuleLDAP : public Module, public Pipe
for (i = 0, num = config.Enumerate("ldap"); i < num; ++i)
{
if (config.ReadValue("ldap", "name", "", i) == cname)
if (config.ReadValue("ldap", "name", "main", i) == cname)
{
break;
}
@@ -250,6 +253,7 @@ class ModuleLDAP : public Module, public Pipe
Log(LOG_NORMAL, "ldap") << "LDAP: Removing server connection " << cname;
s->SetExitState();
s->Wakeup();
this->LDAPServices.erase(cname);
}
}
+1 -1
View File
@@ -186,7 +186,7 @@ class ModuleSQL : public Module, public Pipe
for (i = 0, num = config.Enumerate("mysql"); i < num; ++i)
{
if (config.ReadValue("mysql", "name", "", i) == cname)
if (config.ReadValue("mysql", "name", "main", i) == cname)
{
break;
}
+1 -1
View File
@@ -68,7 +68,7 @@ class IdentifyInterface : public LDAPInterface, public Command
ircdproto->SendAccountLogin(u, u->Account());
ircdproto->SetAutoIdentificationToken(u);
if (this_na && this_na->nc == na->nc)
if (this_na && this_na->nc == na->nc && this_na->nc->HasFlag(NI_UNCONFIRMED) == false)
u->SetMode(NickServ, UMODE_REGISTERED);
u->UpdateHost();
+2 -1
View File
@@ -296,7 +296,8 @@ class BahamutIRCdMessage : public IRCdMessage
if (user->timestamp == convertTo<time_t>(params[7]) && (na = findnick(user->nick)))
{
user->Login(na->nc);
user->SetMode(NickServ, UMODE_REGISTERED);
if (na->nc->HasFlag(NI_UNCONFIRMED) == false)
user->SetMode(NickServ, UMODE_REGISTERED);
}
else
validate_user(user);
+2 -1
View File
@@ -296,7 +296,8 @@ class InspircdIRCdMessage : public IRCdMessage
if (na && na->nc->GetExtRegular("authenticationtoken", svidbuf) && svidbuf == params[0])
{
user->Login(na->nc);
user->SetMode(NickServ, UMODE_REGISTERED);
if (na->nc->HasFlag(NI_UNCONFIRMED))
user->SetMode(NickServ, UMODE_REGISTERED);
}
else
validate_user(user);
+1 -1
View File
@@ -264,7 +264,7 @@ bool event_metadata(const Anope::string &source, const std::vector<Anope::string
if (u && nc)
{
u->Login(nc);
if (user_na && user_na->nc == nc)
if (user_na && user_na->nc == nc && user_na->nc->HasFlag(NI_UNCONFIRMED) == false)
u->SetMode(NickServ, UMODE_REGISTERED);
}
}
+1 -1
View File
@@ -274,7 +274,7 @@ bool event_metadata(const Anope::string &source, const std::vector<Anope::string
if (u && nc)
{
u->Login(nc);
if (user_na && user_na->nc == nc)
if (user_na && user_na->nc == nc && user_na->nc->HasFlag(NI_UNCONFIRMED) == false)
u->SetMode(NickServ, UMODE_REGISTERED);
}
}
+1 -1
View File
@@ -526,7 +526,7 @@ bool event_encap(const Anope::string &source, const std::vector<Anope::string> &
if (u && nc)
{
u->Login(nc);
if (user_na && user_na->nc == nc)
if (user_na && user_na->nc == nc && user_na->nc->HasFlag(NI_UNCONFIRMED) == false)
u->SetMode(NickServ, UMODE_REGISTERED);
}
}
+4 -2
View File
@@ -427,7 +427,8 @@ class Unreal32IRCdMessage : public IRCdMessage
if (na && user->timestamp == convertTo<time_t>(params[6]))
{
user->Login(na->nc);
user->SetMode(NickServ, UMODE_REGISTERED);
if (na->nc->HasFlag(NI_UNCONFIRMED) == false)
user->SetMode(NickServ, UMODE_REGISTERED);
}
else
validate_user(user);
@@ -448,7 +449,8 @@ class Unreal32IRCdMessage : public IRCdMessage
if (na && user->timestamp == convertTo<time_t>(params[6]))
{
user->Login(na->nc);
user->SetMode(NickServ, UMODE_REGISTERED);
if (na->nc->HasFlag(NI_UNCONFIRMED) == false)
user->SetMode(NickServ, UMODE_REGISTERED);
}
else
validate_user(user);
+1 -1
View File
@@ -65,7 +65,7 @@ void mod_run_cmd(BotInfo *bi, User *u, ChannelInfo *ci, Command *c, const Anope:
// Command requires registered users only
if (!c->HasFlag(CFLAG_ALLOW_UNREGISTERED) && !u->IsIdentified())
{
u->SendMessage(bi, _(_(NICK_IDENTIFY_REQUIRED)), Config->s_NickServ.c_str());
u->SendMessage(bi, _(NICK_IDENTIFY_REQUIRED), Config->s_NickServ.c_str());
Log(LOG_COMMAND, "denied", bi) << "Access denied for unregistered user " << u->GetMask() << " with command " << command;
PopLanguage();
return;
+3 -2
View File
@@ -480,7 +480,7 @@ bool ValidateEmailReg(ServerConfig *config, const Anope::string &tag, const Anop
{
if (config->NSEmailReg)
{
if (value.equals_ci("preregexpire"))
if (value.equals_ci("unconfirmedexpire"))
{
if (!data.GetInteger() && !dotime(data.GetValue()))
throw ConfigException("The value for <" + tag + ":" + value + "> must be non-zero when e-mail registration are enabled!");
@@ -1070,6 +1070,7 @@ void ServerConfig::Read()
{"nickserv", "emailregistration", "no", new ValueContainerBool(&this->NSEmailReg), DT_BOOLEAN, NoValidation},
{"nickserv", "modules", "", new ValueContainerString(&NickCoreModules), DT_STRING, NoValidation},
{"nickserv", "forceemail", "no", new ValueContainerBool(&this->NSForceEmail), DT_BOOLEAN, ValidateEmailReg},
{"nickserv", "confirmemailchanges", "no", new ValueContainerBool(&this->NSConfirmEmailChanges), DT_BOOLEAN, NoValidation},
{"nickserv", "defaults", "secure memosignon memoreceive", new ValueContainerString(&NSDefaults), DT_STRING, NoValidation},
{"nickserv", "languages", "", new ValueContainerString(&this->Languages), DT_STRING, NoValidation},
{"nickserv", "defaultlanguage", "0", new ValueContainerString(&this->NSDefLanguage), DT_STRING, NoValidation},
@@ -1078,7 +1079,7 @@ void ServerConfig::Read()
{"nickserv", "expire", "21d", new ValueContainerTime(&this->NSExpire), DT_TIME, NoValidation},
{"nickserv", "suspendexpire", "0", new ValueContainerTime(&this->NSSuspendExpire), DT_TIME, NoValidation},
{"nickserv", "forbidexpire", "0", new ValueContainerTime(&this->NSForbidExpire), DT_TIME, NoValidation},
{"nickserv", "preregexpire", "0", new ValueContainerTime(&this->NSRExpire), DT_TIME, ValidateEmailReg},
{"nickserv", "unconfirmedexpire", "0", new ValueContainerTime(&this->NSUnconfirmedExpire), DT_TIME, ValidateEmailReg},
{"nickserv", "maxaliases", "0", new ValueContainerUInt(&this->NSMaxAliases), DT_UINTEGER, NoValidation},
{"nickserv", "accessmax", "0", new ValueContainerUInt(&this->NSAccessMax), DT_UINTEGER, ValidateNotZero},
{"nickserv", "enforceruser", "", new ValueContainerString(&temp_nsuserhost), DT_STRING, ValidateNotEmpty},
-21
View File
@@ -37,27 +37,6 @@ void MailThread::Run()
SetExitState();
}
bool Mail(User *u, NickRequest *nr, BotInfo *service, const Anope::string &subject, const Anope::string &message)
{
if (!u || !nr || !service || subject.empty() || message.empty())
return false;
if (!Config->UseMail)
u->SendMessage(service, _("Services have been configured to not send mail."));
else if (Anope::CurTime - u->lastmail < Config->MailDelay)
u->SendMessage(service, _("Please wait \002%d\002 seconds and retry."), Config->MailDelay - Anope::CurTime - u->lastmail);
else if (nr->email.empty())
u->SendMessage(service, _("E-mail for \002%s\002 is invalid."), nr->nick.c_str());
else
{
u->lastmail = nr->lastmail = Anope::CurTime;
threadEngine.Start(new MailThread(nr->nick, nr->email, subject, message));
return true;
}
return false;
}
bool Mail(User *u, NickCore *nc, BotInfo *service, const Anope::string &subject, const Anope::string &message)
{
if (!u || !nc || !service || subject.empty() || message.empty())
-1
View File
@@ -137,7 +137,6 @@ extern void expire_all()
Log(LOG_DEBUG) << "Running expire routines";
expire_nicks();
expire_chans();
expire_requests();
expire_exceptions();
FOREACH_MOD(I_OnDatabaseExpire, OnDatabaseExpire());
+3 -40
View File
@@ -69,43 +69,6 @@ int tolower(char c)
/*************************************************************************/
/**
* merge_args: Take an argument count and argument vector and merge them
* into a single string in which each argument is separated by
* a space.
* @param int Number of Args
* @param argv Array
* @return string of the merged array
*/
const char *merge_args(int argc, const char **argv)
{
int i;
static char s[4096];
char *t;
t = s;
for (i = 0; i < argc; ++i)
t += snprintf(t, sizeof(s) - (t - s), "%s%s", *argv++, i < argc - 1 ? " " : "");
return s;
}
/*
* XXX: temporary "safe" version to avoid casting, it's still ugly.
*/
const char *merge_args(int argc, char **argv)
{
int i;
static char s[4096];
char *t;
t = s;
for (i = 0; i < argc; ++i)
t += snprintf(t, sizeof(s) - (t - s), "%s%s", *argv++, i < argc - 1 ? " " : "");
return s;
}
/*************************************************************************/
NumberList::NumberList(const Anope::string &list, bool descending) : is_valid(true), desc(descending)
{
Anope::string error;
@@ -839,12 +802,12 @@ bool Anope::Match(const Anope::string &str, const Anope::string &mask, bool case
* @param ... any number of parameters
* @return a Anope::string
*/
Anope::string Anope::printf(const char *fmt, ...)
Anope::string Anope::printf(const Anope::string &fmt, ...)
{
va_list args;
char buf[1024];
va_start(args, fmt);
vsnprintf(buf, sizeof(buf), fmt, args);
va_start(args, fmt.c_str());
vsnprintf(buf, sizeof(buf), fmt.c_str(), args);
va_end(args);
return buf;
}
-19
View File
@@ -1,25 +1,6 @@
#include "services.h"
#include "modules.h"
NickRequest::NickRequest(const Anope::string &nickname)
{
if (nickname.empty())
throw CoreException("Empty nick passed to NickRequest constructor");
this->requested = this->lastmail = 0;
this->nick = nickname;
NickRequestList[this->nick] = this;
}
NickRequest::~NickRequest()
{
FOREACH_MOD(I_OnDelNickRequest, OnDelNickRequest(this));
NickRequestList.erase(this->nick);
}
/** Default constructor
* @param nick The nick
* @param nickcore The nickcofe for this nick
-32
View File
@@ -14,7 +14,6 @@
nickalias_map NickAliasList;
nickcore_map NickCoreList;
nickrequest_map NickRequestList;
typedef std::map<Anope::string, NickServCollide *> nickservcollides_map;
typedef std::map<Anope::string, NickServRelease *> nickservreleases_map;
@@ -169,13 +168,6 @@ void ns_init()
int validate_user(User *u)
{
NickRequest *nr = findrequestnick(u->nick);
if (nr)
{
u->SendMessage(NickServ, _(NICK_IS_PREREG));
return 0;
}
NickAlias *na = findnick(u->nick);
if (!na)
return 0;
@@ -291,32 +283,8 @@ void expire_nicks()
}
}
void expire_requests()
{
for (nickrequest_map::const_iterator it = NickRequestList.begin(), it_end = NickRequestList.end(); it != it_end; )
{
NickRequest *nr = it->second;
++it;
if (Config->NSRExpire && Anope::CurTime - nr->requested >= Config->NSRExpire)
{
Log(LOG_NORMAL, "expire") << "Request for nick " << nr->nick << " expiring";
delete nr;
}
}
}
/*************************************************************************/
NickRequest *findrequestnick(const Anope::string &nick)
{
nickrequest_map::const_iterator it = NickRequestList.find(nick);
if (it != NickRequestList.end())
return it->second;
return NULL;
}
NickAlias *findnick(const Anope::string &nick)
{
FOREACH_MOD(I_OnFindNick, OnFindNick(nick));
+2 -1
View File
@@ -806,7 +806,8 @@ User *do_nick(const Anope::string &source, const Anope::string &nick, const Anop
user->UpdateHost();
do_on_id(user);
ircdproto->SetAutoIdentificationToken(user);
user->SetMode(NickServ, UMODE_REGISTERED);
if (na->nc->HasFlag(NI_UNCONFIRMED) == false)
user->SetMode(NickServ, UMODE_REGISTERED);
Log(NickServ) << user->GetMask() << " automatically identified for group " << user->Account()->display;
}