saslauth: Cleanup module, don't refuse logins if we can't provide them

This commit is contained in:
Kyle Fuller
2012-03-30 21:52:35 +01:00
parent 27f42d1118
commit 2a4940f23e
+56 -44
View File
@@ -20,29 +20,28 @@ public:
MODCONSTRUCTOR(CSASLAuthMod) {
m_Cache.SetTTL(60000/*ms*/);
}
virtual ~CSASLAuthMod() {}
virtual bool OnBoot() {
return true;
virtual ~CSASLAuthMod() {
sasl_done();
}
virtual bool OnLoad(const CString& sArgs, CString& sMessage) {
VCString vsChans;
VCString vsArgs;
VCString::const_iterator it;
sArgs.Split(" ", vsChans, false);
sArgs.Split(" ", vsArgs, false);
for (it = vsChans.begin(); it != vsChans.end(); ++it) {
if (it->StrCmp("saslauthd") || it->StrCmp("auxprop")) {
method += *it + " ";
}
else {
for (it = vsArgs.begin(); it != vsArgs.end(); ++it) {
if (it->Equals("saslauthd") || it->Equals("auxprop")) {
m_sMethod += *it + " ";
} else {
CUtils::PrintError("Ignoring invalid SASL pwcheck method: " + *it);
sMessage = "Ignored invalid SASL pwcheck method";
}
}
method.TrimRight();
if (method.empty()) {
m_sMethod.TrimRight();
if (m_sMethod.empty()) {
sMessage = "Need a pwcheck method as argument (saslauthd, auxprop)";
return false;
}
@@ -52,60 +51,73 @@ public:
return false;
}
m_cbs[0].id = SASL_CB_GETOPT;
m_cbs[0].proc = reinterpret_cast<int(*)()>(CSASLAuthMod::getopt);
m_cbs[0].context = this;
m_cbs[1].id = SASL_CB_LIST_END;
m_cbs[1].proc = NULL;
m_cbs[1].context = NULL;
return true;
}
virtual EModRet OnLoginAttempt(CSmartPtr<CAuthBase> Auth) {
CString const user(Auth->GetUsername());
CString const pass(Auth->GetPassword());
CUser* pUser(CZNC::Get().FindUser(user));
sasl_conn_t *sasl_conn(0);
const CString& sUsername = Auth->GetUsername();
const CString& sPassword = Auth->GetPassword();
CUser *pUser(CZNC::Get().FindUser(sUsername));
sasl_conn_t *sasl_conn(NULL);
if (!pUser) { // @todo Will want to do some sort of && !m_bAllowCreate in the future
Auth->RefuseLogin("Invalid User - Halting SASL Authentication");
if (!pUser) {
/* @todo Will want to do some sort of &&
* !m_bAllowCreate in the future */
return CONTINUE;
}
const CString sCacheKey(CString(sUsername + ":" + sPassword).MD5());
if (m_Cache.HasItem(sCacheKey)) {
DEBUG("saslauth: Found [" + sUsername + "] in cache");
Auth->AcceptLogin(*pUser);
return HALT;
}
CString const key(CString(user + ":" + pass).MD5());
if (m_Cache.HasItem(key)) {
if (sasl_server_new("znc", NULL, NULL, NULL, NULL, m_cbs, 0, &sasl_conn) == SASL_OK &&
sasl_checkpass(sasl_conn, sUsername.c_str(), sUsername.size(), sPassword.c_str(), sPassword.size()) == SASL_OK) {
m_Cache.AddItem(sCacheKey);
DEBUG("saslauth: Successful SASL authentication [" + sUsername + "]");
sasl_dispose(&sasl_conn);
Auth->AcceptLogin(*pUser);
DEBUG("+++ Found in cache");
}
else if (sasl_server_new("znc", NULL, NULL, NULL, NULL, cbs, 0, &sasl_conn) == SASL_OK &&
sasl_checkpass(sasl_conn, user.c_str(), user.size(), pass.c_str(), pass.size()) == SASL_OK) {
Auth->AcceptLogin(*pUser);
m_Cache.AddItem(key);
DEBUG("+++ Successful SASL password check");
}
else {
Auth->RefuseLogin("SASL Authentication failed");
DEBUG("--- FAILED SASL password check");
return HALT;
}
sasl_dispose(&sasl_conn);
return HALT;
return CONTINUE;
}
private:
const CString& GetMethod() const { return m_sMethod; }
protected:
TCacheMap<CString> m_Cache;
static sasl_callback_t cbs[];
static CString method;
sasl_callback_t m_cbs[2];
CString m_sMethod;
static int getopt(void *context, const char *plugin_name, const char *option, const char **result, unsigned *len) {
if (!method.empty() && strcmp(option, "pwcheck_method") == 0) {
*result = method.c_str();
static int getopt(void *context, const char *plugin_name,
const char *option, const char **result, unsigned *len) {
if (CString(option).Equals("pwcheck_method")) {
*result = ((CSASLAuthMod*)context)->GetMethod().c_str();
return SASL_OK;
}
return SASL_CONTINUE;
}
};
sasl_callback_t CSASLAuthMod::cbs[] = {
{ SASL_CB_GETOPT, reinterpret_cast<int(*)()>(CSASLAuthMod::getopt), NULL },
{ SASL_CB_LIST_END, NULL, NULL }
};
CString CSASLAuthMod::method;
template<> void TModInfo<CSASLAuthMod>(CModInfo& Info) {
Info.SetWikiPage("saslauth");
}
GLOBALMODULEDEFS(CSASLAuthMod, "Allow users to authenticate via SASL password verification method")