if(!IsCapable(source_p, CLICAP_SASL))
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");
return;
}
+ if (*parv[1] == ':' || strchr(parv[1], ' '))
+ {
+ exit_client(client_p, client_p, client_p, "Malformed AUTHENTICATE");
+ return;
+ }
+
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);
return;
if(!*source_p->id)
{
/* Allocate a UID. */
- strcpy(source_p->id, generate_uid());
+ rb_strlcpy(source_p->id, generate_uid(), sizeof(source_p->id));
add_to_id_hash(source_p->id, source_p);
}
if(*parv[4] == 'F')
{
sendto_one(target_p, form_str(ERR_SASLFAIL), me.name, EmptyString(target_p->name) ? "*" : target_p->name);
+ /* Failures with zero messages are just "unknown mechanism" errors; don't count those. */
if(target_p->localClient->sasl_messages > 0)
{
- if(throttle_add((struct sockaddr*)&target_p->localClient->ip))
+ if(*target_p->name)
+ {
+ /* Allow 2 tries before rate-limiting as some clients try EXTERNAL
+ * then PLAIN right after it if the auth failed, causing the client to be
+ * rate-limited immediately and not being able to login with SASL.
+ */
+ if (target_p->localClient->sasl_failures++ > 0)
+ target_p->localClient->sasl_next_retry = rb_current_time() + (1 << MIN(target_p->localClient->sasl_failures + 1, 8));
+ }
+ 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);
+ target_p->localClient->sasl_failures = 0;
target_p->localClient->sasl_complete = 1;
ServerStats.is_ssuc++;
}