]> jfr.im git - solanum.git/blobdiff - modules/m_sasl.c
m_sasl: check if the agent is present after every client_exit
[solanum.git] / modules / m_sasl.c
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));
 }