From 15b05f95f0aeed6fe840cf59a69bce2051d9e2ee Mon Sep 17 00:00:00 2001 From: Simon Arlott Date: Sun, 12 Aug 2018 12:16:51 +0100 Subject: [PATCH] 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. --- include/hook.h | 1 + ircd/client.c | 16 +++++++++------ ircd/hook.c | 2 ++ modules/m_sasl.c | 51 ++++++++++++++++++++++++++++++++++++------------ 4 files changed, 52 insertions(+), 18 deletions(-) diff --git a/include/hook.h b/include/hook.h index eb8c1a6d..58a94d41 100644 --- a/include/hook.h +++ b/include/hook.h @@ -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; diff --git a/ircd/client.c b/ircd/client.c index 43e2e032..3378bc4a 100644 --- a/ircd/client.c +++ b/ircd/client.c @@ -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; } /* diff --git a/ircd/hook.c b/ircd/hook.c index a15afdd0..70defd1c 100644 --- a/ircd/hook.c +++ b/ircd/hook.c @@ -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"); diff --git a/modules/m_sasl.c b/modules/m_sasl.c index 69f7dee8..284e4c93 100644 --- a/modules/m_sasl.c +++ b/modules/m_sasl.c @@ -1,6 +1,7 @@ /* modules/m_sasl.c * Copyright (C) 2006 Michael Tharp * 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)); }