m_sasl: check if the agent is present after every client_exit

When a server disconnects the client_exit hook will only be called once
but there could be multiple servers and clients behind that server.

After any client exits, check if the agent is still present.
This commit is contained in:
Simon Arlott 2018-08-12 12:16:51 +01:00
parent bfd95f010b
commit 15b05f95f0
No known key found for this signature in database
GPG key ID: 49BFFEEFD4C3ED53
4 changed files with 52 additions and 18 deletions

View file

@ -23,6 +23,7 @@ extern int h_burst_finished;
extern int h_server_introduced;
extern int h_server_eob;
extern int h_client_exit;
extern int h_after_client_exit;
extern int h_umode_changed;
extern int h_new_local_user;
extern int h_new_remote_user;

View file

@ -1626,6 +1626,8 @@ exit_client(struct Client *client_p, /* The local client originating the
const char *comment /* Reason for the exit */
)
{
int ret = -1;
hook_data_client_exit hdata;
if(IsClosing(source_p))
return -1;
@ -1646,23 +1648,25 @@ exit_client(struct Client *client_p, /* The local client originating the
{
/* Local clients of various types */
if(IsPerson(source_p))
return exit_local_client(client_p, source_p, from, comment);
ret = exit_local_client(client_p, source_p, from, comment);
else if(IsServer(source_p))
return exit_local_server(client_p, source_p, from, comment);
ret = exit_local_server(client_p, source_p, from, comment);
/* IsUnknown || IsConnecting || IsHandShake */
else if(!IsReject(source_p))
return exit_unknown_client(client_p, source_p, from, comment);
ret = exit_unknown_client(client_p, source_p, from, comment);
}
else
{
/* Remotes */
if(IsPerson(source_p))
return exit_remote_client(client_p, source_p, from, comment);
ret = exit_remote_client(client_p, source_p, from, comment);
else if(IsServer(source_p))
return exit_remote_server(client_p, source_p, from, comment);
ret = exit_remote_server(client_p, source_p, from, comment);
}
return -1;
call_hook(h_after_client_exit, NULL);
return ret;
}
/*

View file

@ -52,6 +52,7 @@ int h_burst_finished;
int h_server_introduced;
int h_server_eob;
int h_client_exit;
int h_after_client_exit;
int h_umode_changed;
int h_new_local_user;
int h_new_remote_user;
@ -75,6 +76,7 @@ init_hook(void)
h_server_introduced = register_hook("server_introduced");
h_server_eob = register_hook("server_eob");
h_client_exit = register_hook("client_exit");
h_after_client_exit = register_hook("after_client_exit");
h_umode_changed = register_hook("umode_changed");
h_new_local_user = register_hook("new_local_user");
h_new_remote_user = register_hook("new_remote_user");

View file

@ -1,6 +1,7 @@
/* modules/m_sasl.c
* Copyright (C) 2006 Michael Tharp <gxti@partiallystapled.com>
* Copyright (C) 2006 charybdis development team
* Copyright (C) 2016 ChatLounge IRC Network Development Team
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@ -51,11 +52,14 @@ static void me_mechlist(struct MsgBuf *, struct Client *, struct Client *, int,
static void abort_sasl(struct Client *);
static void abort_sasl_exit(hook_data_client_exit *);
static void advertise_sasl(struct Client *);
static void advertise_sasl_exit(hook_data_client_exit *);
static void advertise_sasl_cap(bool);
static void advertise_sasl_new(struct Client *);
static void advertise_sasl_exit(void *);
static void advertise_sasl_config(void *);
static unsigned int CLICAP_SASL = 0;
static char mechlist_buf[BUFSIZE];
static bool sasl_agent_present = false;
struct Message authenticate_msgtab = {
"AUTHENTICATE", 0, 0, 0, 0,
@ -76,13 +80,14 @@ mapi_clist_av1 sasl_clist[] = {
mapi_hfn_list_av1 sasl_hfnlist[] = {
{ "new_local_user", (hookfn) abort_sasl },
{ "client_exit", (hookfn) abort_sasl_exit },
{ "new_remote_user", (hookfn) advertise_sasl },
{ "client_exit", (hookfn) advertise_sasl_exit },
{ "new_remote_user", (hookfn) advertise_sasl_new },
{ "after_client_exit", (hookfn) advertise_sasl_exit },
{ "conf_read_end", (hookfn) advertise_sasl_config },
{ NULL, NULL }
};
static bool
sasl_visible(struct Client *client_p)
sasl_visible(struct Client *ignored)
{
struct Client *agent_p = NULL;
@ -108,13 +113,17 @@ static int
_modinit(void)
{
memset(mechlist_buf, 0, sizeof mechlist_buf);
sasl_agent_present = false;
CLICAP_SASL = capability_put(cli_capindex, "sasl", &capdata_sasl);
advertise_sasl_config(NULL);
return 0;
}
static void
_moddeinit(void)
{
advertise_sasl_cap(false);
capability_orphan(cli_capindex, "sasl");
}
@ -342,7 +351,20 @@ abort_sasl_exit(hook_data_client_exit *data)
}
static void
advertise_sasl(struct Client *client_p)
advertise_sasl_cap(bool available)
{
if (sasl_agent_present != available) {
if (available) {
sendto_local_clients_with_capability(CLICAP_CAP_NOTIFY, ":%s CAP * NEW :sasl", me.name);
} else {
sendto_local_clients_with_capability(CLICAP_CAP_NOTIFY, ":%s CAP * DEL :sasl", me.name);
}
sasl_agent_present = available;
}
}
static void
advertise_sasl_new(struct Client *client_p)
{
if (!ConfigFileEntry.sasl_service)
return;
@ -350,17 +372,22 @@ advertise_sasl(struct Client *client_p)
if (irccmp(client_p->name, ConfigFileEntry.sasl_service))
return;
sendto_local_clients_with_capability(CLICAP_CAP_NOTIFY, ":%s CAP * NEW :sasl", me.name);
advertise_sasl_cap(IsService(client_p));
}
static void
advertise_sasl_exit(hook_data_client_exit *data)
advertise_sasl_exit(void *ignored)
{
if (!ConfigFileEntry.sasl_service)
return;
if (irccmp(data->target->name, ConfigFileEntry.sasl_service))
return;
sendto_local_clients_with_capability(CLICAP_CAP_NOTIFY, ":%s CAP * DEL :sasl", me.name);
if (sasl_agent_present) {
advertise_sasl_cap(sasl_visible(NULL));
}
}
static void
advertise_sasl_config(void *ignored)
{
advertise_sasl_cap(sasl_visible(NULL));
}