Anope IRC Services  Version 2.0
ns_recover.cpp
Go to the documentation of this file.
1 /* NickServ core functions
2  *
3  * (C) 2003-2014 Anope Team
4  * Contact us at team@anope.org
5  *
6  * Please read COPYING and README for further details.
7  *
8  * Based on the original code of Epona by Lara.
9  * Based on the original code of Services by Andy Church.
10  */
11 
12 #include "module.h"
13 #include "modules/ns_cert.h"
14 
15 static ServiceReference<NickServService> nickserv("NickServService", "NickServ");
16 
17 typedef std::map<Anope::string, ChannelStatus> NSRecoverInfo;
18 
20 {
24 
25  public:
26  NSRecoverRequest(Module *o, CommandSource &src, Command *c, const Anope::string &nick, const Anope::string &pass) : IdentifyRequest(o, nick, pass), source(src), cmd(c), user(nick) { }
27 
29  {
30  User *u = User::Find(user, true);
31  if (!source.GetUser() || !source.service)
32  return;
33 
34  NickAlias *na = NickAlias::Find(user);
35  if (!na)
36  return;
37 
38  Log(LOG_COMMAND, source, cmd) << "for " << na->nick;
39 
40  /* Nick is being held by us, release it */
41  if (na->HasExt("HELD"))
42  {
43  nickserv->Release(na);
44  source.Reply(_("Service's hold on \002%s\002 has been released."), na->nick.c_str());
45  }
46  else if (!u)
47  {
48  source.Reply(_("No one is using your nick, and services are not holding it."));
49  }
50  // If the user being recovered is identified for the account of the nick then the user is the
51  // same person that is executing the command, so kill them off (old GHOST command).
52  else if (u->Account() == na->nc)
53  {
54  if (!source.GetAccount() && na->nc->HasExt("NS_SECURE"))
55  {
56  source.GetUser()->Login(u->Account());
57  Log(LOG_COMMAND, source, cmd) << "and was automatically identified to " << u->Account()->display;
58  }
59 
60  if (Config->GetModule("ns_recover")->Get<bool>("restoreonrecover"))
61  {
62  if (!u->chans.empty())
63  {
64  NSRecoverInfo *ei = source.GetUser()->Extend<NSRecoverInfo>("recover");
65  for (User::ChanUserList::iterator it = u->chans.begin(), it_end = u->chans.end(); it != it_end; ++it)
66  (*ei)[it->first->name] = it->second->status;
67  }
68  }
69 
70  u->SendMessage(source.service, _("This nickname has been recovered by %s. If you did not do\n"
71  "this then %s may have your password, and you should change it."),
72  source.GetNick().c_str(), source.GetNick().c_str());
73 
74  Anope::string buf = source.command.upper() + " command used by " + source.GetNick();
75  u->Kill(source.service->nick, buf);
76 
77  source.Reply(_("Ghost with your nick has been killed."));
78 
79  if (IRCD->CanSVSNick)
81  }
82  /* User is not identified or not identified to the same account as the person using this command */
83  else
84  {
85  if (!source.GetAccount() && na->nc->HasExt("NS_SECURE"))
86  {
87  source.GetUser()->Login(na->nc); // Identify the user using the command if they arent identified
88  Log(LOG_COMMAND, source, cmd) << "and was automatically identified to " << na->nick << " (" << na->nc->display << ")";
89  }
90 
91  u->SendMessage(source.service, _("This nickname has been recovered by %s."), source.GetNick().c_str());
92  if (nickserv)
93  nickserv->Collide(u, na);
94 
95  if (IRCD->CanSVSNick)
96  {
97  /* If we can svsnick then release our hold and svsnick the user using the command */
98  nickserv->Release(na);
100  }
101  else
102  source.Reply(_("The user with your nick has been removed. Use this command again\n"
103  "to release services's hold on your nick."));
104  }
105  }
106 
108  {
109  if (NickAlias::Find(GetAccount()) != NULL)
110  {
111  source.Reply(ACCESS_DENIED);
112  if (!GetPassword().empty())
113  {
114  Log(LOG_COMMAND, source, cmd) << "with an invalid password for " << GetAccount();
115  if (source.GetUser())
116  source.GetUser()->BadPassword();
117  }
118  }
119  else
120  source.Reply(NICK_X_NOT_REGISTERED, GetAccount().c_str());
121  }
122 };
123 
124 class CommandNSRecover : public Command
125 {
126  public:
127  CommandNSRecover(Module *creator) : Command(creator, "nickserv/recover", 1, 2)
128  {
129  this->SetDesc(_("Regains control of your nick"));
130  this->SetSyntax(_("\037nickname\037 [\037password\037]"));
131  this->AllowUnregistered(true);
132  }
133 
134  void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
135  {
136  const Anope::string &nick = params[0];
137  const Anope::string &pass = params.size() > 1 ? params[1] : "";
138 
139  User *user = User::Find(nick, true);
140 
141  if (user && source.GetUser() == user)
142  {
143  source.Reply(_("You can't %s yourself!"), source.command.lower().c_str());
144  return;
145  }
146 
147  const NickAlias *na = NickAlias::Find(nick);
148 
149  if (!na)
150  {
151  source.Reply(NICK_X_NOT_REGISTERED, nick.c_str());
152  return;
153  }
154  else if (na->nc->HasExt("NS_SUSPENDED"))
155  {
156  source.Reply(NICK_X_SUSPENDED, na->nick.c_str());
157  return;
158  }
159 
160  bool ok = false;
161  if (source.GetAccount() == na->nc)
162  ok = true;
163  else if (!na->nc->HasExt("NS_SECURE") && source.GetUser() && na->nc->IsOnAccess(source.GetUser()))
164  ok = true;
165 
166  NSCertList *cl = na->nc->GetExt<NSCertList>("certificates");
167  if (source.GetUser() && !source.GetUser()->fingerprint.empty() && cl && cl->FindCert(source.GetUser()->fingerprint))
168  ok = true;
169 
170  if (ok == false && !pass.empty())
171  {
172  NSRecoverRequest *req = new NSRecoverRequest(owner, source, this, na->nick, pass);
173  FOREACH_MOD(OnCheckAuthentication, (source.GetUser(), req));
174  req->Dispatch();
175  }
176  else
177  {
178  NSRecoverRequest req(owner, source, this, na->nick, pass);
179 
180  if (ok)
181  req.OnSuccess();
182  else
183  req.OnFail();
184  }
185  }
186 
187  bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
188  {
189  this->SendSyntax(source);
190  source.Reply(" ");
191  source.Reply(_("Recovers your nick from another user or from services.\n"
192  "If services are currently holding your nick, the hold\n"
193  "will be released. If another user is holding your nick\n"
194  "and is identified they will be killed (similar to the old\n"
195  "GHOST command). If they are not identified they will be\n"
196  "forced off of the nick."));
197  return true;
198  }
199 };
200 
201 class NSRecover : public Module
202 {
205 
206  public:
207  NSRecover(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
208  commandnsrecover(this), recover(this, "recover")
209  {
210 
211  if (Config->GetModule("nickserv")->Get<bool>("nonicknameownership"))
212  throw ModuleException(modname + " can not be used with options:nonicknameownership enabled");
213 
214  }
215 
217  {
218  if (Config->GetModule(this)->Get<bool>("restoreonrecover"))
219  {
220  NSRecoverInfo *ei = recover.Get(u);
221  BotInfo *NickServ = Config->GetClient("NickServ");
222 
223  if (ei != NULL && NickServ != NULL)
224  for (NSRecoverInfo::iterator it = ei->begin(), it_end = ei->end(); it != it_end;)
225  {
226  Channel *c = Channel::Find(it->first);
227  const Anope::string &cname = it->first;
228  ++it;
229 
230  /* User might already be on the channel */
231  if (u->FindChannel(c))
232  this->OnJoinChannel(u, c);
233  else if (IRCD->CanSVSJoin)
234  IRCD->SendSVSJoin(NickServ, u, cname, "");
235  }
236  }
237  }
238 
240  {
241  if (Config->GetModule(this)->Get<bool>("restoreonrecover"))
242  {
243  NSRecoverInfo *ei = recover.Get(u);
244 
245  if (ei != NULL)
246  {
247  NSRecoverInfo::iterator it = ei->find(c->name);
248  if (it != ei->end())
249  {
250  for (size_t i = 0; i < it->second.Modes().length(); ++i)
251  c->SetMode(c->ci->WhoSends(), ModeManager::FindChannelModeByChar(it->second.Modes()[i]), u->GetUID());
252 
253  ei->erase(it);
254  if (ei->empty())
255  recover.Unset(u);
256  }
257  }
258  }
259  }
260 };
261 
Serialize::Reference< NickCore > nc
Definition: account.h:47
Definition: bots.h:24
static NickAlias * Find(const Anope::string &nick)
Definition: nickalias.cpp:121
void Kill(const MessageSource &source, const Anope::string &reason)
Definition: users.cpp:729
bool BadPassword()
Definition: users.cpp:797
void OnUserNickChange(User *u, const Anope::string &oldnick) anope_override
Definition: ns_recover.cpp:216
NSRecoverRequest(Module *o, CommandSource &src, Command *c, const Anope::string &nick, const Anope::string &pass)
Definition: ns_recover.cpp:26
void OnFail() anope_override
Definition: ns_recover.cpp:107
CommandNSRecover(Module *creator)
Definition: ns_recover.cpp:127
Anope::string nick
Definition: account.h:37
#define ACCESS_DENIED
Definition: language.h:73
ChanUserList chans
Definition: users.h:87
void Dispatch()
Definition: account.cpp:57
Definition: users.h:34
T * Extend(const Anope::string &name, const T &what)
Definition: extensible.h:224
#define NICK_X_NOT_REGISTERED
Definition: language.h:79
virtual void SendSVSJoin(const MessageSource &source, User *u, const Anope::string &chan, const Anope::string &param)
Definition: protocol.h:170
void OnJoinChannel(User *u, Channel *c) anope_override
Definition: ns_recover.cpp:239
string upper() const
Definition: anope.h:266
void SetDesc(const Anope::string &d)
Definition: command.cpp:130
void Unset(Extensible *obj) anope_override
Definition: extensible.h:95
CoreExport time_t CurTime
Definition: main.cpp:41
const Anope::string & GetPassword() const
Definition: account.h:251
const Anope::string & GetNick() const
Definition: command.cpp:26
#define FOREACH_MOD(ename, args)
Definition: modules.h:62
void OnSuccess() anope_override
Definition: ns_recover.cpp:28
virtual void SendForceNickChange(User *u, const Anope::string &newnick, time_t when)
Definition: protocol.cpp:324
Definition: Config.cs:26
bool CanSVSNick
Definition: protocol.h:49
Anope::string command
Definition: commands.h:69
void Reply(const char *message,...)
Definition: command.cpp:96
bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
Definition: ns_recover.cpp:187
Reference< BotInfo > service
Definition: commands.h:67
void Execute(CommandSource &source, const std::vector< Anope::string > &params) anope_override
Definition: ns_recover.cpp:134
Anope::string display
Definition: account.h:113
std::map< Anope::string, ChannelStatus > NSRecoverInfo
Definition: ns_recover.cpp:17
static ChannelMode * FindChannelModeByChar(char mode)
Definition: modes.cpp:524
virtual bool FindCert(const Anope::string &entry) const =0
#define anope_override
Definition: services.h:56
bool empty() const
Definition: anope.h:126
CoreExport IRCDProto * IRCD
Definition: protocol.cpp:23
static ServiceReference< NickServService > nickserv("NickServService","NickServ")
#define MODULE_INIT(x)
Definition: modules.h:45
bool AllowUnregistered() const
Definition: command.cpp:159
User * GetUser()
Definition: command.cpp:31
void SetSyntax(const Anope::string &s)
Definition: command.cpp:140
void Login(NickCore *core)
Definition: users.cpp:391
Anope::string user
Definition: ns_recover.cpp:23
Anope::string nick
Definition: users.h:62
NSRecover(const Anope::string &modname, const Anope::string &creator)
Definition: ns_recover.cpp:207
static User * Find(const Anope::string &name, bool nick_only=false)
Definition: users.cpp:815
NickCore * Account() const
Definition: users.cpp:422
static Channel * Find(const Anope::string &name)
Definition: channels.cpp:920
T * Get(const Extensible *obj) const
Definition: extensible.h:103
void SendSyntax(CommandSource &)
Definition: command.cpp:145
NickCore * GetAccount()
Definition: command.cpp:36
const char * c_str() const
Definition: anope.h:117
Definition: logger.h:53
CommandNSRecover commandnsrecover
Definition: ns_recover.cpp:203
bool CanSVSJoin
Definition: protocol.h:51
CommandSource source
Definition: ns_recover.cpp:21
void SendMessage(BotInfo *source, const char *fmt,...)
Definition: users.cpp:320
#define _(x)
Definition: services.h:50
bool HasExt(const Anope::string &name) const
Definition: extensible.cpp:31
PrimitiveExtensibleItem< NSRecoverInfo > recover
Definition: ns_recover.cpp:204
const Anope::string & GetAccount() const
Definition: account.h:250
#define NICK_X_SUSPENDED
Definition: language.h:82
Module * owner
Definition: service.h:84