]> jfr.im git - irc/charybdis-ircd/charybdis.git/commitdiff
m_sasl: check if the agent is present after every client_exit
authorSimon Arlott <sa.me.uk>
Sun, 12 Aug 2018 11:16:51 +0000 (12:16 +0100)
committerSimon Arlott <sa.me.uk>
Sun, 12 Aug 2018 11:55:29 +0000 (12:55 +0100)
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
ircd/client.c
ircd/hook.c
modules/m_sasl.c

index eb8c1a6d47b85a39fe931faff9d3b75826b789b4..58a94d4118832330c9e1be3f54ff97fda2065c98 100644 (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;
index 43e2e032e40c86d1e669d50b0bbecfc07b5154ce..3378bc4a7d30ea3f3de78de82b4cfa6f93b016e9 100644 (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;
 }
 
 /*
index a15afdd0476d7e6f374c0aa2ccab0bf9ed6fb70c..70defd1c3dbfc9f831dfacc0aad94a8fa8a65b10 100644 (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");
index 69f7dee84d804f4fe3127f5d1159fdde71a22201..284e4c93ae966ead3a9b715aa2c81693b70f5dbf 100644 (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;
+       if (sasl_agent_present) {
+               advertise_sasl_cap(sasl_visible(NULL));
+       }
+}
 
-       sendto_local_clients_with_capability(CLICAP_CAP_NOTIFY, ":%s CAP * DEL :sasl", me.name);
+static void
+advertise_sasl_config(void *ignored)
+{
+       advertise_sasl_cap(sasl_visible(NULL));
 }