Anope IRC Services  Version 2.0
m_sasl.cpp
Go to the documentation of this file.
1 /*
2  *
3  * (C) 2014 Anope Team
4  * Contact us at team@anope.org
5  *
6  * Please read COPYING and README for further details.
7  */
8 
9 #include "module.h"
10 #include "modules/sasl.h"
11 #include "modules/ns_cert.h"
12 
13 using namespace SASL;
14 
15 class Plain : public Mechanism
16 {
17  public:
18  Plain(Module *o) : Mechanism(o, "PLAIN") { }
19 
21  {
22  if (m.type == "S")
23  {
24  sasl->SendMessage(sess, "C", "+");
25  }
26  else if (m.type == "C")
27  {
28  Anope::string decoded;
29  Anope::B64Decode(m.data, decoded);
30 
31  size_t p = decoded.find('\0');
32  if (p == Anope::string::npos)
33  return;
34  decoded = decoded.substr(p + 1);
35 
36  p = decoded.find('\0');
37  if (p == Anope::string::npos)
38  return;
39 
40  Anope::string acc = decoded.substr(0, p),
41  pass = decoded.substr(p + 1);
42 
43  if (acc.empty() || pass.empty())
44  return;
45 
46  SASL::IdentifyRequest *req = new SASL::IdentifyRequest(this->owner, m.source, acc, pass);
47  FOREACH_MOD(OnCheckAuthentication, (NULL, req));
48  req->Dispatch();
49  }
50  }
51 };
52 
53 class External : public Mechanism
54 {
56 
58  {
60 
61  Session(Mechanism *m, const Anope::string &u) : SASL::Session(m, u) { }
62  };
63 
64  public:
65  External(Module *o) : Mechanism(o, "EXTERNAL"), certs("CertService", "certs")
66  {
67  if (!IRCD || !IRCD->CanCertFP)
68  throw ModuleException("No CertFP");
69  }
70 
72  {
73  return new Session(this, uid);
74  }
75 
77  {
78  Session *mysess = anope_dynamic_static_cast<Session *>(sess);
79 
80  if (m.type == "S")
81  {
82  mysess->cert = m.ext;
83 
84  sasl->SendMessage(sess, "C", "+");
85  }
86  else if (m.type == "C")
87  {
88  if (!certs)
89  {
90  sasl->Fail(sess);
91  delete sess;
92  return;
93  }
94 
95  NickCore *nc = certs->FindAccountFromCert(mysess->cert);
96  if (!nc || nc->HasExt("NS_SUSPENDED"))
97  {
98  sasl->Fail(sess);
99  delete sess;
100  return;
101  }
102 
103  Log(Config->GetClient("NickServ")) << "A user identified to account " << nc->display << " using SASL EXTERNAL";
104  sasl->Succeed(sess, nc);
105  delete sess;
106  }
107  }
108 };
109 
110 class SASLService : public SASL::Service, public Timer
111 {
112  std::map<Anope::string, SASL::Session *> sessions;
113 
114  public:
115  SASLService(Module *o) : SASL::Service(o), Timer(o, 60, Anope::CurTime, true) { }
116 
118  {
119  for (std::map<Anope::string, Session *>::iterator it = sessions.begin(); it != sessions.end(); it++)
120  delete it->second;
121  }
122 
124  {
125  if (m.target != "*")
126  {
127  Server *s = Server::Find(m.target);
128  if (s != Me)
129  {
130  User *u = User::Find(m.target);
131  if (!u || u->server != Me)
132  return;
133  }
134  }
135 
136  Session* &session = sessions[m.source];
137 
138  if (m.type == "S")
139  {
140  ServiceReference<Mechanism> mech("SASL::Mechanism", m.data);
141  if (!mech)
142  {
143  Session tmp(NULL, m.source);
144 
145  sasl->SendMechs(&tmp);
146  sasl->Fail(&tmp);
147  return;
148  }
149 
150  if (!session)
151  session = mech->CreateSession(m.source);
152  }
153  else if (m.type == "D")
154  {
155  delete session;
156  sessions.erase(m.source);
157  return;
158  }
159 
160  if (session && session->mech)
161  session->mech->ProcessMessage(session, m);
162  }
163 
165  {
166  Anope::string agent = Config->GetModule(Service::owner)->Get<Anope::string>("agent", "NickServ");
167  BotInfo *bi = Config->GetClient(agent);
168  if (bi)
169  agent = bi->GetUID();
170  return agent;
171  }
172 
174  {
175  std::map<Anope::string, Session *>::iterator it = sessions.find(uid);
176  if (it != sessions.end())
177  return it->second;
178  return NULL;
179  }
180 
182  {
183  sessions.erase(sess->uid);
184  }
185 
187  {
188  for (std::map<Anope::string, Session *>::iterator it = sessions.begin(); it != sessions.end();)
189  {
190  std::map<Anope::string, Session *>::iterator del = it++;
191  if (*del->second->mech == mech)
192  {
193  if (da)
194  this->SendMessage(del->second, "D", "A");
195  delete del->second;
196  }
197  }
198  }
199 
200  void SendMessage(Session *session, const Anope::string &mtype, const Anope::string &data) anope_override
201  {
202  SASL::Message msg;
203  msg.source = this->GetAgent();
204  msg.target = session->uid;
205  msg.type = mtype;
206  msg.data = data;
207 
208  IRCD->SendSASLMessage(msg);
209  }
210 
212  {
213  IRCD->SendSVSLogin(session->uid, nc->display);
214  this->SendMessage(session, "D", "S");
215  }
216 
217  void Fail(Session *session) anope_override
218  {
219  this->SendMessage(session, "D", "F");
220  }
221 
223  {
224  std::vector<Anope::string> mechs = Service::GetServiceKeys("SASL::Mechanism");
225  Anope::string buf;
226  for (unsigned j = 0; j < mechs.size(); ++j)
227  buf += "," + mechs[j];
228 
229  this->SendMessage(session, "M", buf.empty() ? "" : buf.substr(1));
230  }
231 
232  void Tick(time_t) anope_override
233  {
234  for (std::map<Anope::string, Session *>::iterator it = sessions.begin(); it != sessions.end();)
235  {
236  Anope::string key = it->first;
237  Session *s = it->second;
238  ++it;
239 
240  if (!s || !s->mech || s->created + 60 < Anope::CurTime)
241  {
242  delete s;
243  sessions.erase(key);
244  }
245  }
246  }
247 };
248 
249 class ModuleSASL : public Module
250 {
252 
255 
256  public:
257  ModuleSASL(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
258  sasl(this), plain(this), external(NULL)
259  {
260  try
261  {
262  external = new External(this);
263  }
264  catch (ModuleException &) { }
265  }
266 
268  {
269  delete external;
270  }
271 };
272 
Definition: bots.h:24
Anope::string target
Definition: sasl.h:14
Definition: servers.h:42
Anope::string source
Definition: sasl.h:13
Definition: timers.h:18
void ProcessMessage(Session *sess, const SASL::Message &m) anope_override
Definition: m_sasl.cpp:20
SASLService(Module *o)
Definition: m_sasl.cpp:115
Anope::string data
Definition: sasl.h:16
void Dispatch()
Definition: account.cpp:57
Definition: users.h:34
Session(Mechanism *m, const Anope::string &u)
Definition: m_sasl.cpp:61
External(Module *o)
Definition: m_sasl.cpp:65
CoreExport time_t CurTime
Definition: main.cpp:41
Anope::string cert
Definition: m_sasl.cpp:59
#define FOREACH_MOD(ename, args)
Definition: modules.h:62
void DeleteSessions(Mechanism *mech, bool da) anope_override
Definition: m_sasl.cpp:186
time_t created
Definition: sasl.h:47
string substr(size_type pos=0, size_type n=npos) const
Definition: anope.h:277
void ProcessMessage(SASL::Session *sess, const SASL::Message &m) anope_override
Definition: m_sasl.cpp:76
void SendMechs(Session *session) anope_override
Definition: m_sasl.cpp:222
virtual void SendSASLMessage(const SASL::Message &)
Definition: protocol.h:231
static std::vector< Anope::string > GetServiceKeys(const Anope::string &t)
Definition: service.h:60
Definition: Config.cs:26
bool CanCertFP
Definition: protocol.h:67
void Tick(time_t) anope_override
Definition: m_sasl.cpp:232
void SendMessage(Session *session, const Anope::string &mtype, const Anope::string &data) anope_override
Definition: m_sasl.cpp:200
static const size_type npos
Definition: anope.h:44
static ServiceReference< SASL::Service > sasl("SASL::Service","sasl")
void Succeed(Session *session, NickCore *nc) anope_override
Definition: m_sasl.cpp:211
CoreExport void B64Decode(const string &src, string &target)
Definition: base64.cpp:123
virtual Session * CreateSession(const Anope::string &uid)
Definition: sasl.h:65
External * external
Definition: m_sasl.cpp:254
Anope::string display
Definition: account.h:113
#define anope_override
Definition: services.h:56
bool empty() const
Definition: anope.h:126
ServiceReference< CertService > certs
Definition: m_sasl.cpp:55
Anope::string GetAgent() anope_override
Definition: m_sasl.cpp:164
static Server * Find(const Anope::string &name, bool name_only=false)
Definition: servers.cpp:337
void Fail(Session *session) anope_override
Definition: m_sasl.cpp:217
CoreExport IRCDProto * IRCD
Definition: protocol.cpp:23
void ProcessMessage(const SASL::Message &m) anope_override
Definition: m_sasl.cpp:123
#define MODULE_INIT(x)
Definition: modules.h:45
Server * server
Definition: users.h:77
~SASLService()
Definition: m_sasl.cpp:117
Anope::string type
Definition: sasl.h:15
Plain(Module *o)
Definition: m_sasl.cpp:18
ModuleSASL(const Anope::string &modname, const Anope::string &creator)
Definition: m_sasl.cpp:257
Reference< Mechanism > mech
Definition: sasl.h:49
void RemoveSession(Session *sess) anope_override
Definition: m_sasl.cpp:181
static User * Find(const Anope::string &name, bool nick_only=false)
Definition: users.cpp:815
Session * CreateSession(const Anope::string &uid) anope_override
Definition: m_sasl.cpp:71
Definition: m_sasl.cpp:15
T anope_dynamic_static_cast(O ptr)
Definition: anope.h:774
CoreExport Server * Me
Definition: servers.cpp:24
std::map< Anope::string, SASL::Session * > sessions
Definition: m_sasl.cpp:112
SASLService sasl
Definition: m_sasl.cpp:251
Plain plain
Definition: m_sasl.cpp:253
Definition: logger.h:53
~ModuleSASL()
Definition: m_sasl.cpp:267
size_type find(const string &_str, size_type pos=0) const
Definition: anope.h:192
virtual void SendSVSLogin(const Anope::string &uid, const Anope::string &acc)
Definition: protocol.h:232
bool HasExt(const Anope::string &name) const
Definition: extensible.cpp:31
Definition: defs.h:55
Definition: anope.h:20
Module * owner
Definition: service.h:84
Session * GetSession(const Anope::string &uid) anope_override
Definition: m_sasl.cpp:173