nickserv.cpp

Go to the documentation of this file.
00001 /* NickServ core functions
00002  *
00003  * (C) 2003-2012 Anope Team
00004  * Contact us at team@anope.org
00005  *
00006  * Please read COPYING and README for further details.
00007  *
00008  * Based on the original code of Epona by Lara.
00009  * Based on the original code of Services by Andy Church.
00010  */
00011 
00012 /*************************************************************************/
00013 
00014 #include "module.h"
00015 #include "nickserv.h"
00016 
00017 class NickServCollide;
00018 class NickServRelease;
00019 
00020 typedef std::map<Anope::string, NickServCollide *> nickservcollides_map;
00021 typedef std::map<Anope::string, NickServRelease *> nickservreleases_map;
00022 
00023 static nickservcollides_map NickServCollides;
00024 static nickservreleases_map NickServReleases;
00025 
00028 class NickServCollide : public Timer
00029 {
00030         dynamic_reference<User> u;
00031         Anope::string nick;
00032 
00033  public:
00038         NickServCollide(User *user, time_t delay) : Timer(delay), u(user), nick(u->nick)
00039         {
00040                 /* Erase the current collide and use the new one */
00041                 nickservcollides_map::iterator nit = NickServCollides.find(user->nick);
00042                 if (nit != NickServCollides.end())
00043                         delete nit->second;
00044 
00045                 NickServCollides.insert(std::make_pair(nick, this));
00046         }
00047 
00050         virtual ~NickServCollide()
00051         {
00052                 NickServCollides.erase(this->nick);
00053         }
00054 
00058         void Tick(time_t t) anope_override
00059         {
00060                 if (!u)
00061                         return;
00062                 /* If they identified or don't exist anymore, don't kill them. */
00063                 NickAlias *na = findnick(u->nick);
00064                 if (!na || u->Account() == na->nc || u->timestamp > this->GetSetTime())
00065                         return;
00066 
00067                 u->Collide(na);
00068         }
00069 };
00070 
00071 class MyNickServService : public NickServService
00072 {
00073  public:
00074         MyNickServService(Module *m) : NickServService(m) { }
00075 
00076         void Validate(User *u) anope_override
00077         {
00078                 NickAlias *na = findnick(u->nick);
00079                 if (!na)
00080                         return;
00081                 const BotInfo *NickServ = findbot(Config->NickServ);
00082 
00083                 if (na->nc->HasFlag(NI_SUSPENDED))
00084                 {
00085                         u->SendMessage(NickServ, NICK_X_SUSPENDED, u->nick.c_str());
00086                         u->Collide(na);
00087                         return;
00088                 }
00089 
00090                 if (!(u->Account() == na->nc) && !u->fingerprint.empty() && na->nc->FindCert(u->fingerprint))
00091                 {
00092                         u->SendMessage(NickServ, _("SSL Fingerprint accepted, you are now identified."));
00093                         Log(u) << "automatically identified for account " << na->nc->display << " using a valid SSL fingerprint.";
00094                         u->Identify(na);
00095                         return;
00096                 }
00097 
00098                 if (!na->nc->HasFlag(NI_SECURE) && u->IsRecognized())
00099                 {
00100                         na->last_seen = Anope::CurTime;
00101                         Anope::string last_usermask = u->GetIdent() + "@" + u->GetDisplayedHost();
00102                         na->last_usermask = last_usermask;
00103                         na->last_realname = u->realname;
00104                         return;
00105                 }
00106 
00107                 if (Config->NoNicknameOwnership)
00108                         return;
00109 
00110                 if (u->IsRecognized(false) || !na->nc->HasFlag(NI_KILL_IMMED))
00111                 {
00112                         if (na->nc->HasFlag(NI_SECURE))
00113                                 u->SendMessage(NickServ, NICK_IS_SECURE, Config->UseStrictPrivMsgString.c_str(), Config->NickServ.c_str());
00114                         else
00115                                 u->SendMessage(NickServ, NICK_IS_REGISTERED, Config->UseStrictPrivMsgString.c_str(), Config->NickServ.c_str());
00116                 }
00117 
00118                 if (na->nc->HasFlag(NI_KILLPROTECT) && !u->IsRecognized(false))
00119                 {
00120                         if (na->nc->HasFlag(NI_KILL_IMMED))
00121                         {
00122                                 u->SendMessage(NickServ, FORCENICKCHANGE_NOW);
00123                                 u->Collide(na);
00124                         }
00125                         else if (na->nc->HasFlag(NI_KILL_QUICK))
00126                         {
00127                                 u->SendMessage(NickServ, _("If you do not change within %s, I will change your nick."), duration(Config->NSKillQuick, u->Account()).c_str());
00128                                 new NickServCollide(u, Config->NSKillQuick);
00129                         }
00130                         else
00131                         {
00132                                 u->SendMessage(NickServ, _("If you do not change within %s, I will change your nick."), duration(Config->NSKill, u->Account()).c_str());
00133                                 new NickServCollide(u, Config->NSKill);
00134                         }
00135                 }
00136 
00137         }
00138 };
00139 
00140 class ExpireCallback : public CallBack
00141 {
00142  public:
00143         ExpireCallback(Module *owner) : CallBack(owner, Config->ExpireTimeout, Anope::CurTime, true) { }
00144 
00145         void Tick(time_t) anope_override
00146         {
00147                 if (noexpire || readonly)
00148                         return;
00149 
00150                 for (nickalias_map::const_iterator it = NickAliasList->begin(), it_end = NickAliasList->end(); it != it_end; )
00151                 {
00152                         NickAlias *na = it->second;
00153                         ++it;
00154 
00155                         User *u = finduser(na->nick);
00156                         if (u && (na->nc->HasFlag(NI_SECURE) ? u->IsIdentified(true) : u->IsRecognized()))
00157                                 na->last_seen = Anope::CurTime;
00158 
00159                         bool expire = false;
00160 
00161                         if (na->nc->HasFlag(NI_UNCONFIRMED))
00162                                 if (Config->NSUnconfirmedExpire && Anope::CurTime - na->time_registered >= Config->NSUnconfirmedExpire)
00163                                         expire = true;
00164                         if (Config->NSExpire && Anope::CurTime - na->last_seen >= Config->NSExpire)
00165                                 expire = true;
00166                         if (na->HasFlag(NS_NO_EXPIRE))
00167                                 expire = false;
00168 
00169                         FOREACH_MOD(I_OnPreNickExpire, OnPreNickExpire(na, expire));
00170                 
00171                         if (expire)
00172                         {
00173                                 Anope::string extra;
00174                                 if (na->nc->HasFlag(NI_SUSPENDED))
00175                                         extra = "suspended ";
00176                                 Log(LOG_NORMAL, "expire") << "Expiring " << extra << "nickname " << na->nick << " (group: " << na->nc->display << ") (e-mail: " << (na->nc->email.empty() ? "none" : na->nc->email) << ")";
00177                                 FOREACH_MOD(I_OnNickExpire, OnNickExpire(na));
00178                                 na->destroy();
00179                         }
00180                 }
00181         }
00182 };
00183 
00184 class NickServCore : public Module
00185 {
00186         MyNickServService mynickserv;
00187         ExpireCallback expires;
00188 
00189  public:
00190         NickServCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), mynickserv(this), expires(this)
00191         {
00192                 this->SetAuthor("Anope");
00193 
00194                 if (!findbot(Config->NickServ))
00195                         throw ModuleException("No bot named " + Config->NickServ);
00196 
00197                 Implementation i[] = { I_OnDelNick, I_OnDelCore, I_OnChangeCoreDisplay, I_OnNickIdentify, I_OnNickGroup,
00198                 I_OnNickUpdate, I_OnUserNickChange, I_OnPreHelp, I_OnPostHelp, I_OnUserConnect };
00199                 ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation));
00200         }
00201 
00202         void OnDelNick(NickAlias *na) anope_override
00203         {
00204                 User *u = finduser(na->nick);
00205                 if (u && u->Account() == na->nc)
00206                 {
00207                         ircdproto->SendLogout(u);
00208                         u->RemoveMode(findbot(Config->NickServ), UMODE_REGISTERED);
00209                         u->Logout();
00210                 }
00211         }
00212 
00213         void OnDelCore(NickCore *nc) anope_override
00214         {
00215                 Log(findbot(Config->NickServ), "nick") << "deleting nickname group " << nc->display;
00216 
00217                 /* Clean up this nick core from any users online using it
00218                  * (ones that /nick but remain unidentified)
00219                  */
00220                 for (std::list<User *>::iterator it = nc->Users.begin(); it != nc->Users.end();)
00221                 {
00222                         User *user = *it++;
00223                         ircdproto->SendLogout(user);
00224                         user->RemoveMode(findbot(Config->NickServ), UMODE_REGISTERED);
00225                         user->Logout();
00226                         FOREACH_MOD(I_OnNickLogout, OnNickLogout(user));
00227                 }
00228                 nc->Users.clear();
00229         }
00230 
00231         void OnChangeCoreDisplay(NickCore *nc, const Anope::string &newdisplay) anope_override
00232         {
00233                 Log(LOG_NORMAL, "nick", findbot(Config->NickServ)) << "Changing " << nc->display << " nickname group display to " << newdisplay;
00234         }
00235 
00236         void OnNickIdentify(User *u) anope_override
00237         {
00238                 const BotInfo *NickServ = findbot(Config->NickServ);
00239 
00240                 if (!Config->NoNicknameOwnership)
00241                 {
00242                         const NickAlias *this_na = findnick(u->nick);
00243                         if (this_na && this_na->nc == u->Account() && u->Account()->HasFlag(NI_UNCONFIRMED) == false)
00244                                 u->SetMode(NickServ, UMODE_REGISTERED);
00245                 }
00246 
00247                 if (Config->NSModeOnID)
00248                         for (UChannelList::iterator it = u->chans.begin(), it_end = u->chans.end(); it != it_end; ++it)
00249                         {
00250                                 ChannelContainer *cc = *it;
00251                                 Channel *c = cc->chan;
00252                                 if (c)
00253                                         chan_set_correct_modes(u, c, 1, true);
00254                         }
00255 
00256                 if (!Config->NSModesOnID.empty())
00257                         u->SetModes(NickServ, "%s", Config->NSModesOnID.c_str());
00258 
00259                 if (Config->NSForceEmail && u->Account()->email.empty())
00260                 {
00261                         u->SendMessage(NickServ, _("You must now supply an e-mail for your nick.\n"
00262                                                         "This e-mail will allow you to retrieve your password in\n"
00263                                                         "case you forget it."));
00264                         u->SendMessage(NickServ, _("Type \002%s%s SET EMAIL \037e-mail\037\002 in order to set your e-mail.\n"
00265                                                         "Your privacy is respected; this e-mail won't be given to\n"
00266                                                         "any third-party person."), Config->UseStrictPrivMsgString.c_str(), Config->NickServ.c_str());
00267                 }
00268 
00269                 if (u->Account()->HasFlag(NI_UNCONFIRMED))
00270                 {
00271                         u->SendMessage(NickServ, _("Your email address is not confirmed. To confirm it, follow the instructions that were emailed to you when you registered."));
00272                         const NickAlias *this_na = findnick(u->Account()->display);
00273                         time_t time_registered = Anope::CurTime - this_na->time_registered;
00274                         if (Config->NSUnconfirmedExpire > time_registered)
00275                                 u->SendMessage(NickServ, _("Your account will expire, if not confirmed, in %s"), duration(Config->NSUnconfirmedExpire - time_registered).c_str());
00276                 }
00277         }
00278 
00279         void OnNickGroup(User *u, NickAlias *target) anope_override
00280         {
00281                 if (target->nc->HasFlag(NI_UNCONFIRMED) == false)
00282                         u->SetMode(findbot(Config->NickServ), UMODE_REGISTERED);
00283         }
00284 
00285         void OnNickUpdate(User *u) anope_override
00286         {
00287                 for (UChannelList::iterator it = u->chans.begin(), it_end = u->chans.end(); it != it_end; ++it)
00288                 {
00289                         ChannelContainer *cc = *it;
00290                         Channel *c = cc->chan;
00291                         if (c)
00292                                 chan_set_correct_modes(u, c, 1, false);
00293                 }
00294         }
00295 
00296         void OnUserNickChange(User *u, const Anope::string &oldnick) anope_override
00297         {
00298                 const NickAlias *na = findnick(u->nick);
00299                 const BotInfo *NickServ = findbot(Config->NickServ);
00300                 /* If the new nick isnt registerd or its registerd and not yours */
00301                 if (!na || na->nc != u->Account())
00302                 {
00303                         /* Remove +r, but keep an account associated with the user */
00304                         u->RemoveMode(NickServ, UMODE_REGISTERED);
00305 
00306                         this->mynickserv.Validate(u);
00307                 }
00308                 else
00309                 {
00310                         /* Reset +r and re-send account (even though it really should be set at this point) */
00311                         ircdproto->SendLogin(u);
00312                         if (!Config->NoNicknameOwnership && na->nc == u->Account() && na->nc->HasFlag(NI_UNCONFIRMED) == false)
00313                                 u->SetMode(NickServ, UMODE_REGISTERED);
00314                         Log(NickServ) << u->GetMask() << " automatically identified for group " << u->Account()->display;
00315                 }
00316         }
00317 
00318         void OnUserModeSet(User *u, UserModeName Name) anope_override
00319         {
00320                 if (Name == UMODE_REGISTERED && !u->IsIdentified())
00321                         u->RemoveMode(findbot(Config->NickServ), Name);
00322         }
00323 
00324         EventReturn OnPreHelp(CommandSource &source, const std::vector<Anope::string> &params) anope_override
00325         {
00326                 if (!params.empty() || source.c || source.service->nick != Config->NickServ)
00327                         return EVENT_CONTINUE;
00328                 source.Reply(_("\002%s\002 allows you to \"register\" a nickname and\n"
00329                         "prevent others from using it. The following\n"
00330                         "commands allow for registration and maintenance of\n"
00331                         "nicknames; to use them, type \002%s%s \037command\037\002.\n"
00332                         "For more information on a specific command, type\n"
00333                         "\002%s%s %s \037command\037\002.\n "), Config->NickServ.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->NickServ.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->NickServ.c_str(), source.command.c_str());
00334                 return EVENT_CONTINUE;
00335         }
00336 
00337         void OnPostHelp(CommandSource &source, const std::vector<Anope::string> &params) anope_override
00338         {
00339                 if (!params.empty() || source.c || source.service->nick != Config->NickServ)
00340                         return;
00341                 if (source.IsServicesOper())
00342                         source.Reply(_(" \n"
00343                                 "Services Operators can also drop any nickname without needing\n"
00344                                 "to identify for the nick, and may view the access list for\n"
00345                                 "any nickname."));
00346                 if (Config->NSExpire >= 86400)
00347                         source.Reply(_(" \n"
00348                                 "Nicknames that are not used anymore are subject to \n"
00349                                 "the automatic expiration, i.e. they will be deleted\n"
00350                                 "after %d days if not used."), Config->NSExpire / 86400);
00351                 source.Reply(_(" \n"
00352                         "\002NOTICE:\002 This service is intended to provide a way for\n"
00353                         "IRC users to ensure their identity is not compromised.\n"
00354                         "It is \002NOT\002 intended to facilitate \"stealing\" of\n"
00355                         "nicknames or other malicious actions. Abuse of %s\n"
00356                         "will result in, at minimum, loss of the abused\n"
00357                         "nickname(s)."), Config->NickServ.c_str());
00358         }
00359 
00360         void OnUserConnect(dynamic_reference<User> &u, bool &exempt) anope_override
00361         {
00362                 if (!Config->NoNicknameOwnership && !Config->NSUnregisteredNotice.empty() && u && !findnick(u->nick))
00363                         u->SendMessage(findbot(Config->NickServ), Config->NSUnregisteredNotice);
00364         }
00365 };
00366 
00367 MODULE_INIT(NickServCore)
00368