From: Stephan Bosch Date: Sun, 26 Mar 2023 15:47:08 +0000 (+0200) Subject: auth: sasl-server - Create new per-instance mechanism registry X-Git-Tag: 2.4.2~222 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=e89b269da863d9add38d3c8bb8452cdedddc98b4;p=thirdparty%2Fdovecot%2Fcore.git auth: sasl-server - Create new per-instance mechanism registry --- diff --git a/src/auth/sasl-server-mech.c b/src/auth/sasl-server-mech.c index c91dbadb74..e5ff69c32c 100644 --- a/src/auth/sasl-server-mech.c +++ b/src/auth/sasl-server-mech.c @@ -1,9 +1,35 @@ /* Copyright (c) 2023 Dovecot authors, see the included COPYING file */ #include "auth-common.h" +#include "llist.h" #include "sasl-server-private.h" +/* + * Accessors + */ + +const char *sasl_server_mech_get_name(const struct sasl_server_mech *mech) +{ + return mech->def->name; +} + +enum sasl_mech_security_flags +sasl_server_mech_get_security_flags(const struct sasl_server_mech *mech) +{ + return mech->def->flags; +} + +enum sasl_mech_passdb_need +sasl_server_mech_get_passdb_need(const struct sasl_server_mech *mech) +{ + return mech->def->passdb_need; +} + +/* + * Common functions + */ + void sasl_server_mech_generic_auth_initial( struct sasl_server_mech_request *mreq, const unsigned char *data, size_t data_size) @@ -18,3 +44,138 @@ void sasl_server_mech_generic_auth_initial( mech->funcs->auth_continue(mreq, data, data_size); } } + +/* + * Registry + */ + +static struct sasl_server_mech_reg * +sasl_server_mech_reg_find(struct sasl_server_instance *sinst, const char *name) +{ + struct sasl_server_mech_reg *mech_reg; + name = t_str_ucase(name); + + for (mech_reg = sinst->mechs_head; mech_reg != NULL; + mech_reg = mech_reg->next) { + if (strcmp(mech_reg->mech->def->name, name) == 0) + return mech_reg; + } + return NULL; +} + +static struct sasl_server_mech * +sasl_server_mech_create(struct sasl_server_instance *sinst, + const struct sasl_server_mech_def *def) +{ + struct sasl_server_mech *mech; + + mech = p_new(sinst->pool, struct sasl_server_mech, 1); + mech->pool = sinst->pool; + mech->sinst = sinst; + mech->def = def; + + mech->event = event_create(sinst->event); + event_drop_parent_log_prefixes(mech->event, 1); + event_set_append_log_prefix(mech->event, + t_strdup_printf("sasl(%s): ", t_str_lcase(def->name))); + + return mech; +} + +static void sasl_server_mech_free(struct sasl_server_mech *mech) +{ + event_unref(&mech->event); + mech->def = NULL; +} + +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_reg *mech_reg; + struct sasl_server_mech *mech; + + i_assert(sasl_server_mech_reg_find(sinst, def->name) == NULL); + + mech_reg = p_new(sinst->pool, struct sasl_server_mech_reg, 1); + + mech = sasl_server_mech_create(sinst, def); + mech->reg = mech_reg; + mech_reg->mech = mech; + + return mech; +} + +struct sasl_server_mech * +sasl_server_mech_register(struct sasl_server_instance *sinst, + const struct sasl_server_mech_def *def) +{ + struct sasl_server_mech *mech; + + mech = sasl_server_mech_register_common(sinst, def); + DLLIST2_APPEND(&sinst->mechs_head, &sinst->mechs_tail, mech->reg); + + return mech; +} + +struct sasl_server_mech * +sasl_server_mech_register_hidden(struct sasl_server_instance *sinst, + const struct sasl_server_mech_def *def) +{ + struct sasl_server_mech *mech; + + mech = sasl_server_mech_register_common(sinst, def); + DLLIST_PREPEND(&sinst->mechs_hidden, mech->reg); + + return mech; +} + +const struct sasl_server_mech * +sasl_server_mech_find(struct sasl_server_instance *sinst, const char *name) +{ + struct sasl_server_mech_reg *mech_reg; + + mech_reg = sasl_server_mech_reg_find(sinst, name); + if (mech_reg == NULL) + return NULL; + return mech_reg->mech; +} + +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) +{ + struct sasl_server_mech_reg *mech_reg; + + mech_reg = mech_reg_list; + while (mech_reg != NULL) { + struct sasl_server_mech_reg *mech_reg_next = mech_reg->next; + + if (mech_reg->mech->def == def) + return mech_reg; + mech_reg = mech_reg_next; + } + return NULL; +} + +void sasl_server_mech_unregister(struct sasl_server_instance *sinst, + const struct sasl_server_mech_def *def) +{ + struct sasl_server_mech_reg *mech_reg; + + mech_reg = sasl_server_mech_reg_list_find(sinst->mechs_head, def); + if (mech_reg != NULL) { + DLLIST2_REMOVE(&sinst->mechs_head, + &sinst->mechs_tail, mech_reg); + } else { + mech_reg = sasl_server_mech_reg_list_find( + sinst->mechs_hidden, def); + if (mech_reg != NULL) + DLLIST_REMOVE(&sinst->mechs_hidden, mech_reg); + } + + if (mech_reg == NULL) + return; + + sasl_server_mech_free(mech_reg->mech); +} diff --git a/src/auth/sasl-server-private.h b/src/auth/sasl-server-private.h index 6ef13ebb51..dbb5677baf 100644 --- a/src/auth/sasl-server-private.h +++ b/src/auth/sasl-server-private.h @@ -19,6 +19,11 @@ struct sasl_server_request { sasl_server_mech_passdb_callback_t *passdb_callback; }; +struct sasl_server_mech_reg { + struct sasl_server_mech *mech; + struct sasl_server_mech_reg *prev, *next; +}; + struct sasl_server_instance { struct sasl_server *server; pool_t pool; @@ -27,6 +32,9 @@ struct sasl_server_instance { struct event *event; struct sasl_server_settings set; + struct sasl_server_mech_reg *mechs_head, *mechs_tail; + struct sasl_server_mech_reg *mechs_hidden; + unsigned int requests; }; diff --git a/src/auth/sasl-server-protected.h b/src/auth/sasl-server-protected.h index 35fe5b30bf..af042fd6ce 100644 --- a/src/auth/sasl-server-protected.h +++ b/src/auth/sasl-server-protected.h @@ -46,6 +46,15 @@ struct mechanisms_register { buffer_t *handshake_cbind; }; +struct sasl_server_mech { + struct sasl_server_instance *sinst; + struct sasl_server_mech_reg *reg; + pool_t pool; + struct event *event; + + const struct sasl_server_mech_def *def; +}; + struct sasl_server_mech_request { pool_t pool; const struct sasl_server_mech_def *mech; @@ -68,6 +77,15 @@ struct sasl_server_mech_request { extern const struct sasl_server_mech_def mech_dovecot_token; +struct sasl_server_mech * ATTR_NOWARN_UNUSED_RESULT +sasl_server_mech_register(struct sasl_server_instance *sinst, + const struct sasl_server_mech_def *def); +struct sasl_server_mech * ATTR_NOWARN_UNUSED_RESULT +sasl_server_mech_register_hidden(struct sasl_server_instance *sinst, + const struct sasl_server_mech_def *def); +void sasl_server_mech_unregister(struct sasl_server_instance *sinst, + const struct sasl_server_mech_def *def); + void mech_register_module(const struct sasl_server_mech_def *module); void mech_unregister_module(const struct sasl_server_mech_def *module); const struct sasl_server_mech_def *mech_module_find(const char *name); diff --git a/src/auth/sasl-server.h b/src/auth/sasl-server.h index 0ed6e3b5bf..5f4a22ec8e 100644 --- a/src/auth/sasl-server.h +++ b/src/auth/sasl-server.h @@ -5,6 +5,7 @@ struct sasl_passdb_result; struct sasl_server_mech_def; +struct sasl_server_mech; struct sasl_server_request; struct sasl_server_req_ctx; struct sasl_server_instance; @@ -148,6 +149,20 @@ void sasl_server_request_input(struct sasl_server_req_ctx *rctx, void sasl_server_request_test_set_authid(struct sasl_server_req_ctx *rctx, const char *authid); +/* + * Mechanism + */ + +const char * ATTR_PURE +sasl_server_mech_get_name(const struct sasl_server_mech *mech); +enum sasl_mech_security_flags ATTR_PURE +sasl_server_mech_get_security_flags(const struct sasl_server_mech *mech); +enum sasl_mech_passdb_need ATTR_PURE +sasl_server_mech_get_passdb_need(const struct sasl_server_mech *mech); + +const struct sasl_server_mech * +sasl_server_mech_find(struct sasl_server_instance *sinst, const char *name); + /* * Instance */