From 03f04cd80ece62a330e54c3174bba3a1ab71c661 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 + modules/m_sasl.c | 73 ++++++++++++++++++++++++++++++++++++++++-------- src/client.c | 16 +++++++---- src/hook.c | 2 ++ 4 files changed, 74 insertions(+), 18 deletions(-) diff --git a/include/hook.h b/include/hook.h index 70d1b5ad..7044368a 100644 --- a/include/hook.h +++ b/include/hook.h @@ -25,6 +25,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/modules/m_sasl.c b/modules/m_sasl.c index f1b3f3df..4ec3cc95 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 @@ -49,8 +50,12 @@ static int me_sasl(struct Client *, struct Client *, int, const char **); 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(int); +static void advertise_sasl_new(struct Client *); +static void advertise_sasl_exit(void *); +static void advertise_sasl_config(void *); + +static int sasl_agent_present = 0; struct Message authenticate_msgtab = { "AUTHENTICATE", 0, 0, 0, MFLG_SLOW, @@ -67,12 +72,38 @@ 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 } }; -DECLARE_MODULE_AV1(sasl, NULL, NULL, sasl_clist, NULL, sasl_hfnlist, "$Revision: 1409 $"); +static int +sasl_visible(void) +{ + struct Client *agent_p = NULL; + + if (ConfigFileEntry.sasl_service) + agent_p = find_named_client(ConfigFileEntry.sasl_service); + + return agent_p != NULL && IsService(agent_p); +} + +static int +_modinit(void) +{ + sasl_agent_present = 0; + advertise_sasl_config(NULL); + return 0; +} + +static void +_moddeinit(void) +{ + advertise_sasl_cap(0); +} + +DECLARE_MODULE_AV1(sasl, _modinit, _moddeinit, sasl_clist, NULL, sasl_hfnlist, "$Revision: 1409 $"); static int m_authenticate(struct Client *client_p, struct Client *source_p, @@ -261,7 +292,20 @@ abort_sasl_exit(hook_data_client_exit *data) } static void -advertise_sasl(struct Client *client_p) +advertise_sasl_cap(int 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; @@ -269,17 +313,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()); + } +} + +static void +advertise_sasl_config(void *ignored) +{ + advertise_sasl_cap(sasl_visible()); } diff --git a/src/client.c b/src/client.c index 7e1e43b4..7d4973a7 100644 --- a/src/client.c +++ b/src/client.c @@ -1568,6 +1568,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; @@ -1588,23 +1590,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/src/hook.c b/src/hook.c index 24e924b6..0dd8da29 100644 --- a/src/hook.c +++ b/src/hook.c @@ -59,6 +59,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; @@ -86,6 +87,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");