Parse network and client from authzid. Tests will be in future commit

This commit is contained in:
Alexey Sokolov
2025-02-24 09:21:30 +00:00
parent ed20d489b6
commit 8778a2bb5d
4 changed files with 32 additions and 11 deletions
+15 -3
View File
@@ -258,14 +258,25 @@ class CClient : public CIRCSocket {
void AcceptSASLLogin(CUser& User);
/** Start potentially asynchronous process of checking the credentials.
* When finished, will send the success/failure SASL numerics to the
* client. This is mostly useful for SASL PLAIN. */
void StartSASLPasswordCheck(const CString& sUser, const CString& sPassword);
* client. This is mostly useful for SASL PLAIN.
* sAuthorizationId is internally passed through ParseUser() to extract
* network and client id.
* Currently sUser should match the username from
* sAuthorizationId: either in full, or just the username part; but in a
* future version we may add an ability to actually login as a different
* user, but with your password.
*/
void StartSASLPasswordCheck(const CString& sUser, const CString& sPassword,
const CString& sAuthorizationId);
/** Gathers username, client id, network name, if present. Returns username
* cleaned from client id and network name.
*/
CString ParseUser(const CString& sAuthLine);
private:
void HandleCap(const CMessage& Message);
void RespondCap(const CString& sResponse);
void ParsePass(const CString& sAuthLine);
void ParseUser(const CString& sAuthLine);
void ParseIdentifier(const CString& sAuthLine);
template <typename T>
@@ -322,6 +333,7 @@ class CClient : public CIRCSocket {
CIRCNetwork* m_pNetwork;
CString m_sNick;
CString m_sPass;
// User who didn't necessarily login yet, or might not even exist.
CString m_sUser;
CString m_sNetwork;
CString m_sIdentifier;
+3
View File
@@ -1388,6 +1388,9 @@ class CModule {
* GetClient()->SendSASLChallenge(), or reject authentication by calling
* GetClient()->RefuseSASLLogin(), or accept it by calling
* GetClient()->AcceptSASLLogin().
* At some point before accepting the login, you should call
* GetClient()->ParseUser(authz-id) to let it know the network name to
* attach to and the client id.
* @param sMechanism The SASL mechanism selected by the client.
* @param sMessage The SASL opaque value/credentials sent by the client,
* after debase64ing and concatenating if it was split.
+3 -5
View File
@@ -36,13 +36,11 @@ class CSASLMechanismPlain : public CModule {
CString sAuthcId = sMessage.Token(1, false, sNullSeparator, true);
CString sPassword = sMessage.Token(2, false, sNullSeparator, true);
if (!sAuthzId.empty() && sAuthzId != sAuthcId) {
// Reject custom SASL plain authorization identifiers
GetClient()->RefuseSASLLogin("No support for custom AuthzId");
return HALTMODS;
if (sAuthzId.empty()) {
sAuthzId = sAuthcId;
}
GetClient()->StartSASLPasswordCheck(sAuthcId, sPassword);
GetClient()->StartSASLPasswordCheck(sAuthcId, sPassword, sAuthzId);
return HALTMODS;
}
};
+11 -3
View File
@@ -387,8 +387,14 @@ class CClientSASLAuth : public CClientAuth {
void RefusedLogin(const CString& sReason) override;
};
void CClient::StartSASLPasswordCheck(const CString& sUser, const CString& sPassword) {
m_spAuth = std::make_shared<CClientSASLAuth>(this, sUser, sPassword);
void CClient::StartSASLPasswordCheck(const CString& sUser,
const CString& sPassword, const CString& sAuthorizationId) {
ParseUser(sAuthorizationId);
if (sUser != m_sUser && sUser != sAuthorizationId) {
RefuseSASLLogin("No support for custom AuthzId");
}
m_spAuth = std::make_shared<CClientSASLAuth>(this, m_sUser, sPassword);
CZNC::Get().AuthUser(m_spAuth);
}
@@ -973,7 +979,7 @@ void CClient::ParsePass(const CString& sAuthLine) {
}
}
void CClient::ParseUser(const CString& sAuthLine) {
CString CClient::ParseUser(const CString& sAuthLine) {
// user[@identifier][/network]
const size_t uSlash = sAuthLine.rfind("/");
@@ -984,6 +990,8 @@ void CClient::ParseUser(const CString& sAuthLine) {
} else {
ParseIdentifier(sAuthLine);
}
return m_sUser;
}
void CClient::ParseIdentifier(const CString& sAuthLine) {