summaryrefslogtreecommitdiff
path: root/include/modules/nickserv/sasl.h
blob: 99f654e481b41baa0f6e2a281775d4071b97bb67 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
/*
 *
 * (C) 2014-2025 Anope Team
 * Contact us at team@anope.org
 *
 * Please read COPYING and README for further details.
 */

#pragma once

namespace SASL
{
	class Mechanism;
	struct Message;
	class ProtocolInterface;
	struct Service;
	struct Session;

	/** The SASL interface implemented by the protocol modules. */
	static ServiceReference<SASL::ProtocolInterface> protocol_interface("SASL::ProtocolInterface", "sasl");

	/** The SASL interface implemented by ns_sasl. */
	static ServiceReference<SASL::Service> service("SASL::Service", "sasl");
}

/** Represents a single SASL message. */
struct SASL::Message final
{
	/** The source UID or name. */
	Anope::string source;

	/** The target UID or name. */
	Anope::string target;

	/** The type of message. */
	Anope::string type;

	/** One or more data parameters. */
	std::vector<Anope::string> data;
};

/** Sends IRCd messages used by the SASL module. */
class SASL::ProtocolInterface
	: public ::Service
{
protected:
	ProtocolInterface(Module *o)
		: ::Service(o, "SASL::ProtocolInterface", "sasl")
	{
	}

public:
	/** Sends the list of SASL mechanisms to the IRCd
	 * @param mechs The list of SASL mechanisms.
	 */
	virtual void SendSASLMechanisms(std::vector<Anope::string> &mechs) { };

	/** Sends a SASL message to the IRCd.
	 * @param message The SASL message to send.
	 */
	virtual void SendSASLMessage(const SASL::Message &message) = 0;

	/** Sends a login or logout for \p uid to \p na.
	 * @param uid The uid of the user to log in.
	 * @param na The nick alias to log the user in as or logout if nullptr.
	 */
	virtual void SendSVSLogin(const Anope::string &uid, NickAlias *na) = 0;
};

/** SASL service interface. */
struct SASL::Service
	: ::Service
{
	Service(Module *o)
		: ::Service(o, "SASL::Service", "sasl")
	{
	}

	virtual void DeleteSessions(Mechanism *mech, bool da = false) = 0;

	/** Fails a SASL session. This notifies the client and increments the
	 * failed attempt counter which may kill the client if the bad password
	 * limit has been reached.
	 *
	 * @param sess The session to fail.
	 */
	virtual void Fail(Session *sess) = 0;

	/** Retrieves the session for the specified user identifier. */
	virtual Session *GetSession(const Anope::string &uid) = 0;

	/** Processes a SASL authentication message from the uplink.
	 * @param m The message to process.
	 */
	virtual void ProcessMessage(const Message &m) = 0;

	/** Removes the specified SASL session from the service.
	 * @param sess The session to remove.
	 */
	virtual void RemoveSession(Session *sess) = 0;

	/** Sends a SASL message for the specified session.
	 * @param type The type of message to send.
	 * @param data The contents of the SASL message.
	 */
	virtual void SendMessage(SASL::Session *sess, const Anope::string &type, const Anope::string &data) = 0;

	/** Completes a successful authentication.
	 * @param sess The session which finished authentication.
	 * @param nc The account which has been logged into.
	 */
	virtual void Succeed(Session *sess, NickCore *nc) = 0;
};

/** Represents a single SASL session. */
struct SASL::Session
{
	/** The time at which the session was created. */
	const time_t created;

	/** The hostname and IP address of the authenticating user. */
	Anope::string hostname, ip;

	/** A reference to the mechanism that the session is authenticating using. */
	Reference<Mechanism> mech;

	/** The unique identifier of the authenticating user. */
	const Anope::string uid;

	/** Creates a new authentication session.
	 * @param m The mechanism that the session is authenticating with.
	 * @param u The unique identifier of the authenticating user.
	 */
	Session(Mechanism *m, const Anope::string &u)
		: created(Anope::CurTime)
		, mech(m)
		, uid(u)
	{
	}

	virtual ~Session()
	{
		if (service)
			service->RemoveSession(this);
	}

	/** Retrieves a description of the user this session is associated with. */
	inline Anope::string GetUserInfo()
	{
		auto *u = User::Find(uid);
		if (u)
			return u->GetMask();
		if (!hostname.empty() && !ip.empty())
			return Anope::printf("%s (%s)", hostname.c_str(), ip.c_str());
		return "A user";
	};
};

/* Represents an authentication mechanism. */
class SASL::Mechanism
	: public ::Service
{
protected:
	/** Creates a new authentication mechanism.
	 * @param o The module that owns this instance.
	 * @param sname The name of the authentication mechanism (e.g. PLAIN).
	 */
	Mechanism(Module *o, const Anope::string &sname)
		: Service(o, "SASL::Mechanism", sname)
	{
	}

public:
	virtual ~Mechanism()
	{
		if (service)
			service->DeleteSessions(this, true);
	}

	/** Creates a new SASL session.
	 * @param uid The unique identifier of the authenticating user.
	 */
	virtual Session *CreateSession(const Anope::string &uid)
	{
		return new Session(this, uid);
	}

	/** Processes an authentication message from the authenticating user.
	 * @param session The session for which the message applies.
	 * @param m The message sent by the user.
	 * @return True if the message was processed successfully or false if
	 *         the session should be aborted.
	 */
	virtual bool ProcessMessage(Session *sess, const Message &m) = 0;
};