]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
auth: sasl-server - Create global mechanism registry
authorStephan Bosch <stephan.bosch@open-xchange.com>
Sun, 26 Mar 2023 17:07:27 +0000 (19:07 +0200)
committertimo.sirainen <timo.sirainen@open-xchange.com>
Thu, 9 Oct 2025 08:41:22 +0000 (08:41 +0000)
src/auth/sasl-server-mech.c
src/auth/sasl-server-private.h

index e5ff69c32c9d6a840ffd961ffcca9a098fc90a20..df1049840cacd774ae0c8ea0db5399d6f413e840 100644 (file)
@@ -49,6 +49,64 @@ void sasl_server_mech_generic_auth_initial(
  * Registry
  */
 
+static struct sasl_server_mech_def_reg *
+sasl_server_mech_find_def(struct sasl_server *server,
+                         const struct sasl_server_mech_def *def)
+{
+       struct sasl_server_mech_def_reg *mech_dreg;
+
+       mech_dreg = server->mechs_head;
+       while (mech_dreg != NULL) {
+               if (mech_dreg->def == def)
+                       break;
+               mech_dreg = mech_dreg->next;
+       }
+
+       return mech_dreg;
+}
+
+static struct sasl_server_mech_def_reg *
+sasl_server_mech_find_def_by_name(struct sasl_server *server,
+                                 const char *mech_name)
+{
+       struct sasl_server_mech_def_reg *mech_dreg;
+
+       mech_dreg = server->mechs_head;
+       while (mech_dreg != NULL) {
+               if (strcmp(mech_dreg->def->name, mech_name) == 0)
+                       break;
+               mech_dreg = mech_dreg->next;
+       }
+
+       return mech_dreg;
+}
+
+static struct sasl_server_mech_def_reg *
+sasl_server_mech_register_def(struct sasl_server *server,
+                             const struct sasl_server_mech_def *def)
+{
+       struct sasl_server_mech_def_reg *mech_dreg;
+
+       i_assert(def->funcs != NULL);
+       i_assert(strcmp(def->name, t_str_ucase(def->name)) == 0);
+
+       mech_dreg = sasl_server_mech_find_def(server, def);
+       if (mech_dreg != NULL) {
+               i_assert(mech_dreg->refcount > 0);
+               mech_dreg->refcount++;
+               return mech_dreg;
+       }
+
+       i_assert(sasl_server_mech_find_def_by_name(server, def->name) == NULL);
+
+       mech_dreg = p_new(server->pool, struct sasl_server_mech_def_reg, 1);
+       mech_dreg->def = def;
+       mech_dreg->refcount = 1;
+
+       DLLIST2_APPEND(&server->mechs_head, &server->mechs_tail, mech_dreg);
+       return mech_dreg;
+}
+
 static struct sasl_server_mech_reg *
 sasl_server_mech_reg_find(struct sasl_server_instance *sinst, const char *name)
 {
@@ -57,7 +115,7 @@ sasl_server_mech_reg_find(struct sasl_server_instance *sinst, const char *name)
 
        for (mech_reg = sinst->mechs_head; mech_reg != NULL;
             mech_reg = mech_reg->next) {
-               if (strcmp(mech_reg->mech->def->name, name) == 0)
+               if (strcmp(mech_reg->def_reg->def->name, name) == 0)
                        return mech_reg;
        }
        return NULL;
@@ -92,12 +150,18 @@ static struct sasl_server_mech *
 sasl_server_mech_register_common(struct sasl_server_instance *sinst,
                                 const struct sasl_server_mech_def *def)
 {
+       struct sasl_server_mech_def_reg *mech_dreg;
        struct sasl_server_mech_reg *mech_reg;
        struct sasl_server_mech *mech;
 
        i_assert(sasl_server_mech_reg_find(sinst, def->name) == NULL);
 
+       mech_dreg = sasl_server_mech_register_def(sinst->server, def);
+
        mech_reg = p_new(sinst->pool, struct sasl_server_mech_reg, 1);
+       mech_reg->def_reg = mech_dreg;
+
+       DLLIST_PREPEND_FULL(&mech_dreg->insts, mech_reg, def_prev, def_next);
 
        mech = sasl_server_mech_create(sinst, def);
        mech->reg = mech_reg;
@@ -141,6 +205,25 @@ sasl_server_mech_find(struct sasl_server_instance *sinst, const char *name)
        return mech_reg->mech;
 }
 
+static void sasl_server_mech_reg_free(struct sasl_server_mech_reg *mech_reg)
+{
+       struct sasl_server_mech *mech = mech_reg->mech;
+       struct sasl_server_mech_def_reg *mech_dreg = mech_reg->def_reg;
+
+       i_assert(mech_dreg->def == mech->def);
+       DLLIST_REMOVE_FULL(&mech_dreg->insts, mech_reg, def_prev, def_next);
+       mech_reg->mech = NULL;
+       sasl_server_mech_free(mech);
+
+       if (mech_dreg->insts == NULL) {
+               struct sasl_server *server = mech->sinst->server;
+
+               DLLIST2_REMOVE(&server->mechs_head, &server->mechs_tail,
+                              mech_dreg);
+               mech_dreg->def = NULL;
+       }
+}
+
 static struct sasl_server_mech_reg *
 sasl_server_mech_reg_list_find(struct sasl_server_mech_reg *mech_reg_list,
                               const struct sasl_server_mech_def *def)
@@ -177,5 +260,5 @@ void sasl_server_mech_unregister(struct sasl_server_instance *sinst,
        if (mech_reg == NULL)
                return;
 
-       sasl_server_mech_free(mech_reg->mech);
+       sasl_server_mech_reg_free(mech_reg);
 }
index dbb5677baf7bfb34013b0c3de48de61f45914dcd..b1c5f6b7e79867954a3f1a3e34e3b54f8e0e7133 100644 (file)
@@ -22,6 +22,19 @@ struct sasl_server_request {
 struct sasl_server_mech_reg {
        struct sasl_server_mech *mech;
        struct sasl_server_mech_reg *prev, *next;
+
+       struct sasl_server_mech_def_reg *def_reg;
+       struct sasl_server_mech_reg *def_prev, *def_next;
+};
+
+struct sasl_server_mech_def_reg {
+       const struct sasl_server_mech_def *def;
+       unsigned int refcount;
+       struct sasl_server_mech_def_reg *prev, *next;
+
+       struct sasl_server_mech_data *data;
+
+       struct sasl_server_mech_reg *insts;
 };
 
 struct sasl_server_instance {
@@ -45,6 +58,8 @@ struct sasl_server {
 
        struct sasl_server_instance *instances;
 
+       struct sasl_server_mech_def_reg *mechs_head, *mechs_tail;
+
        unsigned int requests;
 };