m_sasl: add configuration option for the nick of the SASL agent

This allows multiple improvements to m_sasl. With this change, the SASL
authentication gets aborted immediately when services are offline.
Additionally, we send the SASL ENCAP messages directly to the specified
SASL agent.
This commit is contained in:
Max Teufel 2015-02-14 10:41:10 +01:00
parent f51b72de97
commit 7d33cce8ef
6 changed files with 45 additions and 6 deletions

View file

@ -461,6 +461,14 @@ general {
default_operstring = "is an IRC Operator"; default_operstring = "is an IRC Operator";
default_adminstring = "is a Server Administrator"; default_adminstring = "is a Server Administrator";
servicestring = "is a Network Service"; servicestring = "is a Network Service";
/*
* Nick of the network's SASL agent. Used to check whether services are here,
* SASL credentials are only sent to its server. Needs to be a service.
*
* Defaults to SaslServ if unspecified.
*/
sasl_service = "SaslServ";
disable_fake_channels = no; disable_fake_channels = no;
tkline_expire_notices = no; tkline_expire_notices = no;
default_floodcount = 10; default_floodcount = 10;

View file

@ -955,6 +955,14 @@ general {
*/ */
servicestring = "is a Network Service"; servicestring = "is a Network Service";
/*
* Nick of the network's SASL agent. Used to check whether services are here,
* SASL credentials are only sent to its server. Needs to be a service.
*
* Defaults to SaslServ if unspecified.
*/
sasl_service = "SaslServ";
/* disable fake channels: disable local users joining fake versions /* disable fake channels: disable local users joining fake versions
* of channels, eg #foo^B^B. Disables bold, mirc colour, reverse, * of channels, eg #foo^B^B. Disables bold, mirc colour, reverse,
* underline and hard space. (ASCII 2, 3, 22, 31, 160 respectively). * underline and hard space. (ASCII 2, 3, 22, 31, 160 respectively).

View file

@ -151,6 +151,8 @@ struct config_file_entry
char *identifyservice; char *identifyservice;
char *identifycommand; char *identifycommand;
char *sasl_service;
char *fname_userlog; char *fname_userlog;
char *fname_fuserlog; char *fname_fuserlog;
char *fname_operlog; char *fname_operlog;

View file

@ -40,6 +40,8 @@
#include "s_serv.h" #include "s_serv.h"
#include "s_stats.h" #include "s_stats.h"
#include "string.h" #include "string.h"
#include "s_newconf.h"
#include "s_conf.h"
static int mr_authenticate(struct Client *, struct Client *, int, const char **); static int mr_authenticate(struct Client *, struct Client *, int, const char **);
static int me_sasl(struct Client *, struct Client *, int, const char **); static int me_sasl(struct Client *, struct Client *, int, const char **);
@ -72,6 +74,7 @@ mr_authenticate(struct Client *client_p, struct Client *source_p,
int parc, const char *parv[]) int parc, const char *parv[])
{ {
struct Client *agent_p = NULL; struct Client *agent_p = NULL;
struct Client *saslserv_p = NULL;
/* They really should use CAP for their own sake. */ /* They really should use CAP for their own sake. */
if(!IsCapable(source_p, CLICAP_SASL)) if(!IsCapable(source_p, CLICAP_SASL))
@ -83,6 +86,13 @@ mr_authenticate(struct Client *client_p, struct Client *source_p,
return 0; return 0;
} }
saslserv_p = find_named_client(ConfigFileEntry.sasl_service);
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 0;
}
if(source_p->preClient->sasl_complete) if(source_p->preClient->sasl_complete)
{ {
sendto_one(source_p, form_str(ERR_SASLALREADY), me.name, EmptyString(source_p->name) ? "*" : source_p->name); sendto_one(source_p, form_str(ERR_SASLALREADY), me.name, EmptyString(source_p->name) ? "*" : source_p->name);
@ -108,16 +118,20 @@ mr_authenticate(struct Client *client_p, struct Client *source_p,
if(agent_p == NULL) if(agent_p == NULL)
{ {
if (!strcmp(parv[1], "EXTERNAL") && source_p->certfp != NULL) if (!strcmp(parv[1], "EXTERNAL") && source_p->certfp != NULL)
sendto_server(NULL, NULL, CAP_TS6|CAP_ENCAP, NOCAPS, ":%s ENCAP * SASL %s * S %s %s", me.id, sendto_one(saslserv_p, ":%s ENCAP %s SASL %s %s S %s %s", me.id, saslserv_p->servptr->name,
source_p->id, parv[1], source_p->id, saslserv_p->id,
source_p->certfp); parv[1], source_p->certfp);
else else
sendto_server(NULL, NULL, CAP_TS6|CAP_ENCAP, NOCAPS, ":%s ENCAP * SASL %s * S %s", me.id, sendto_one(saslserv_p, ":%s ENCAP %s SASL %s %s S %s", me.id, saslserv_p->servptr->name,
source_p->id, parv[1]); source_p->id, saslserv_p->id,
parv[1]);
rb_strlcpy(source_p->preClient->sasl_agent, saslserv_p->id, IDLEN);
} }
else else
sendto_one(agent_p, ":%s ENCAP %s SASL %s %s C %s", me.id, agent_p->servptr->name, sendto_one(agent_p, ":%s ENCAP %s SASL %s %s C %s", me.id, agent_p->servptr->name,
source_p->id, agent_p->id, parv[1]); source_p->id, agent_p->id,
parv[1]);
source_p->preClient->sasl_out++; source_p->preClient->sasl_out++;
return 0; return 0;

View file

@ -2315,6 +2315,7 @@ static struct ConfEntry conf_general_table[] =
{ "kline_reason", CF_QSTRING, NULL, REALLEN, &ConfigFileEntry.kline_reason }, { "kline_reason", CF_QSTRING, NULL, REALLEN, &ConfigFileEntry.kline_reason },
{ "identify_service", CF_QSTRING, NULL, REALLEN, &ConfigFileEntry.identifyservice }, { "identify_service", CF_QSTRING, NULL, REALLEN, &ConfigFileEntry.identifyservice },
{ "identify_command", CF_QSTRING, NULL, REALLEN, &ConfigFileEntry.identifycommand }, { "identify_command", CF_QSTRING, NULL, REALLEN, &ConfigFileEntry.identifycommand },
{ "sasl_service", CF_QSTRING, NULL, REALLEN, &ConfigFileEntry.sasl_service },
{ "anti_spam_exit_message_time", CF_TIME, NULL, 0, &ConfigFileEntry.anti_spam_exit_message_time }, { "anti_spam_exit_message_time", CF_TIME, NULL, 0, &ConfigFileEntry.anti_spam_exit_message_time },
{ "disable_fake_channels", CF_YESNO, NULL, 0, &ConfigFileEntry.disable_fake_channels }, { "disable_fake_channels", CF_YESNO, NULL, 0, &ConfigFileEntry.disable_fake_channels },

View file

@ -692,6 +692,7 @@ set_default_conf(void)
ConfigFileEntry.default_operstring = NULL; ConfigFileEntry.default_operstring = NULL;
ConfigFileEntry.default_adminstring = NULL; ConfigFileEntry.default_adminstring = NULL;
ConfigFileEntry.servicestring = NULL; ConfigFileEntry.servicestring = NULL;
ConfigFileEntry.sasl_service = NULL;
ConfigFileEntry.default_umodes = UMODE_INVISIBLE; ConfigFileEntry.default_umodes = UMODE_INVISIBLE;
ConfigFileEntry.failed_oper_notice = YES; ConfigFileEntry.failed_oper_notice = YES;
@ -886,6 +887,9 @@ validate_conf(void)
if (ConfigFileEntry.servicestring == NULL) if (ConfigFileEntry.servicestring == NULL)
ConfigFileEntry.servicestring = rb_strdup("is a Network Service"); ConfigFileEntry.servicestring = rb_strdup("is a Network Service");
if (ConfigFileEntry.sasl_service == NULL)
ConfigFileEntry.sasl_service = rb_strdup("SaslServ");
/* RFC 1459 says 1 message per 2 seconds on average and bursts of /* RFC 1459 says 1 message per 2 seconds on average and bursts of
* 5 messages are acceptable, so allow at least that. * 5 messages are acceptable, so allow at least that.
*/ */
@ -1489,6 +1493,8 @@ clear_out_old_conf(void)
ConfigFileEntry.servicestring = NULL; ConfigFileEntry.servicestring = NULL;
rb_free(ConfigFileEntry.kline_reason); rb_free(ConfigFileEntry.kline_reason);
ConfigFileEntry.kline_reason = NULL; ConfigFileEntry.kline_reason = NULL;
rb_free(ConfigFileEntry.sasl_service);
ConfigFileEntry.sasl_service = NULL;
/* clean out log */ /* clean out log */
rb_free(ConfigFileEntry.fname_userlog); rb_free(ConfigFileEntry.fname_userlog);