0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-10-05 23:28:53 +02:00

Merge pull request #183 from grawity/sasl-fail-throttle-v3

limit failed SASL authentication attempts
This commit is contained in:
Mantas Mikulėnas 2016-04-11 22:28:33 +03:00
commit 5eb8ce0679
2 changed files with 36 additions and 3 deletions

View file

@ -285,6 +285,10 @@ struct LocalUser
char sasl_agent[IDLEN]; char sasl_agent[IDLEN];
unsigned char sasl_out; unsigned char sasl_out;
unsigned char sasl_complete; unsigned char sasl_complete;
unsigned int sasl_messages;
unsigned int sasl_failures;
time_t sasl_next_retry;
}; };
struct AuthClient struct AuthClient

View file

@ -35,6 +35,7 @@
#include "msg.h" #include "msg.h"
#include "modules.h" #include "modules.h"
#include "numeric.h" #include "numeric.h"
#include "reject.h"
#include "s_serv.h" #include "s_serv.h"
#include "s_stats.h" #include "s_stats.h"
#include "string.h" #include "string.h"
@ -130,14 +131,20 @@ m_authenticate(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *
if(!IsCapable(source_p, CLICAP_SASL)) if(!IsCapable(source_p, CLICAP_SASL))
return; return;
if (strlen(client_p->id) == 3) if(source_p->localClient->sasl_next_retry > rb_current_time())
{
sendto_one(source_p, form_str(RPL_LOAD2HI), me.name, EmptyString(source_p->name) ? "*" : source_p->name, msgbuf_p->cmd);
return;
}
if(strlen(client_p->id) == 3)
{ {
exit_client(client_p, client_p, client_p, "Mixing client and server protocol"); exit_client(client_p, client_p, client_p, "Mixing client and server protocol");
return; return;
} }
saslserv_p = find_named_client(ConfigFileEntry.sasl_service); saslserv_p = find_named_client(ConfigFileEntry.sasl_service);
if (saslserv_p == NULL || !IsService(saslserv_p)) if(saslserv_p == NULL || !IsService(saslserv_p))
{ {
sendto_one(source_p, form_str(ERR_SASLABORTED), me.name, EmptyString(source_p->name) ? "*" : source_p->name); sendto_one(source_p, form_str(ERR_SASLABORTED), me.name, EmptyString(source_p->name) ? "*" : source_p->name);
return; return;
@ -223,17 +230,39 @@ me_sasl(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_
rb_strlcpy(target_p->localClient->sasl_agent, parv[1], IDLEN); rb_strlcpy(target_p->localClient->sasl_agent, parv[1], IDLEN);
if(*parv[3] == 'C') if(*parv[3] == 'C')
{
sendto_one(target_p, "AUTHENTICATE %s", parv[4]); sendto_one(target_p, "AUTHENTICATE %s", parv[4]);
target_p->localClient->sasl_messages++;
}
else if(*parv[3] == 'D') else if(*parv[3] == 'D')
{ {
if(*parv[4] == 'F') if(*parv[4] == 'F')
{
sendto_one(target_p, form_str(ERR_SASLFAIL), me.name, EmptyString(target_p->name) ? "*" : target_p->name); sendto_one(target_p, form_str(ERR_SASLFAIL), me.name, EmptyString(target_p->name) ? "*" : target_p->name);
else if(*parv[4] == 'S') { /* Failures with zero messages are just "unknown mechanism" errors; don't count those. */
if(target_p->localClient->sasl_messages > 0)
{
if(*target_p->name)
{
target_p->localClient->sasl_failures++;
target_p->localClient->sasl_next_retry = rb_current_time() + (1 << MIN(target_p->localClient->sasl_failures + 5, 13));
}
else if(throttle_add((struct sockaddr*)&target_p->localClient->ip))
{
exit_client(target_p, target_p, &me, "Too many failed authentication attempts");
return;
}
}
}
else if(*parv[4] == 'S')
{
sendto_one(target_p, form_str(RPL_SASLSUCCESS), me.name, EmptyString(target_p->name) ? "*" : target_p->name); sendto_one(target_p, form_str(RPL_SASLSUCCESS), me.name, EmptyString(target_p->name) ? "*" : target_p->name);
target_p->localClient->sasl_failures = 0;
target_p->localClient->sasl_complete = 1; target_p->localClient->sasl_complete = 1;
ServerStats.is_ssuc++; ServerStats.is_ssuc++;
} }
*target_p->localClient->sasl_agent = '\0'; /* Blank the stored agent so someone else can answer */ *target_p->localClient->sasl_agent = '\0'; /* Blank the stored agent so someone else can answer */
target_p->localClient->sasl_messages = 0;
} }
else if(*parv[3] == 'M') else if(*parv[3] == 'M')
sendto_one(target_p, form_str(RPL_SASLMECHS), me.name, EmptyString(target_p->name) ? "*" : target_p->name, parv[4]); sendto_one(target_p, form_str(RPL_SASLMECHS), me.name, EmptyString(target_p->name) ? "*" : target_p->name, parv[4]);