NOPLUGIN_LDFLAGS =
if GSSAPI_PLUGIN
-GSSAPI_LIB = libmech_gssapi.la
+GSSAPI_LIB = \
+ libmech_gssapi.la \
+ libmech_gss_spnego.la
endif
if HAVE_LDAP
sasl-server-mech-cram-md5.c \
sasl-server-mech-digest-md5.c \
sasl-server-mech-external.c \
- sasl-server-mech-gssapi.c \
sasl-server-mech-login.c \
sasl-server-mech-oauth2.c \
sasl-server-mech-otp.c \
sasl-server-mech-plain-common.c \
sasl-server-mech-scram.c \
sasl-server-mech-winbind.c
+if HAVE_GSSAPI
+if !GSSAPI_PLUGIN
+sasl_server_mechanisms += \
+ sasl-server-mech-gssapi.c
+endif
+endif
sasl_sources = \
${sasl_server_mechanisms} \
db-oauth2.c \
db-sql.c \
db-passwd-file.c \
- mech.c \
${sasl_sources} \
passdb.c \
passdb-blocking.c \
userdb-sql.c \
$(ldap_sources) \
$(lua_sources)
+if HAVE_GSSAPI
+if !GSSAPI_PLUGIN
+auth_common_sources += \
+ auth-sasl-mech-gssapi.c \
+ auth-sasl-mech-gss-spnego.c
+endif
+endif
headers = \
auth.h \
auth-request-handler-private.h \
auth-request-var-expand.h \
auth-sasl.h \
+ auth-sasl-gssapi.h \
auth-sasl-oauth2.h \
auth-settings.h \
auth-fields.h \
mech-otp.h \
mech-digest-md5-private.h \
sasl-server.h \
+ sasl-server-gssapi.h \
sasl-server-oauth2.h \
+ sasl-server-private.h \
sasl-server-protected.h \
sasl-server-mech-plain-common.h \
sasl-server-mech-scram.h \
libmech_gssapi_la_LDFLAGS = -module -avoid-version
libmech_gssapi_la_LIBADD = $(KRB5_LIBS)
libmech_gssapi_la_CPPFLAGS = $(AM_CPPFLAGS) $(KRB5_CFLAGS) -DPLUGIN_BUILD
-libmech_gssapi_la_SOURCES = sasl-server-mech-gssapi.c
+libmech_gssapi_la_SOURCES = \
+ sasl-server-mech-gssapi.c \
+ auth-sasl-mech-gssapi.c
+
+libmech_gss_spnego_la_LDFLAGS = -module -avoid-version
+libmech_gss_spnego_la_LIBADD = $(KRB5_LIBS)
+libmech_gss_spnego_la_CPPFLAGS = $(AM_CPPFLAGS) $(KRB5_CFLAGS) -DPLUGIN_BUILD
+libmech_gss_spnego_la_SOURCES = \
+ sasl-server-mech-gssapi.c \
+ auth-sasl-mech-gss-spnego.c
endif
if HAVE_LDAP
--- /dev/null
+#ifndef AUTH_SASL_MECH_GSSAPI_H
+#define AUTH_SASL_MECH_GSSAPI_H
+
+#ifdef BUILTIN_GSSAPI
+void auth_sasl_mech_gssapi_register(void);
+void auth_sasl_mech_gss_spnego_register(void);
+#endif
+
+#endif
.auth_initial = mech_apop_auth_initial,
};
-const struct sasl_server_mech_def mech_apop = {
+static const struct sasl_server_mech_def mech_apop = {
.name = AUTH_SASL_MECH_NAME_APOP,
.flags = SASL_MECH_SEC_PRIVATE | SASL_MECH_SEC_DICTIONARY |
.funcs = &mech_apop_funcs,
};
+
+void auth_sasl_mech_register_apop(struct sasl_server_instance *sinst)
+{
+ sasl_server_mech_register(sinst, &mech_apop);
+}
.auth_continue = mech_dovecot_token_auth_continue,
};
-const struct sasl_server_mech_def mech_dovecot_token = {
+static const struct sasl_server_mech_def mech_dovecot_token = {
.name = AUTH_SASL_MECH_NAME_DOVECOT_TOKEN,
.flags = SASL_MECH_SEC_PRIVATE | SASL_MECH_SEC_ALLOW_NULS,
.funcs = &mech_dovecot_token_funcs,
};
+
+const struct sasl_server_mech *
+auth_sasl_mech_register_dovecot_token(struct sasl_server_instance *sinst)
+{
+ return sasl_server_mech_register_hidden(sinst, &mech_dovecot_token);
+}
--- /dev/null
+/* Copyright (c) 2023 Dovecot authors, see the included COPYING file */
+
+#include "auth-common.h"
+#include "sasl-server.h"
+#include "sasl-server-gssapi.h"
+#include "auth-sasl.h"
+#include "auth-sasl-gssapi.h"
+
+#ifdef HAVE_GSSAPI_SPNEGO
+
+static struct auth_sasl_mech_module mech_gss_spnego;
+
+static bool
+mech_gss_spnego_register(struct sasl_server_instance *sasl_inst,
+ const struct auth_settings *set ATTR_UNUSED)
+{
+ sasl_server_mech_register_gss_spnego(sasl_inst);
+ return TRUE;
+}
+
+static void
+mech_gss_spnego_unregister(struct sasl_server_instance *sasl_inst)
+{
+ sasl_server_mech_unregister_gss_spnego(sasl_inst);
+}
+
+static struct auth_sasl_mech_module mech_gss_spnego = {
+ .mech_name = SASL_MECH_NAME_GSS_SPNEGO,
+
+ .mech_register = mech_gss_spnego_register,
+ .mech_unregister = mech_gss_spnego_unregister,
+};
+
+#ifdef BUILTIN_GSSAPI
+void auth_sasl_mech_gss_spnego_register(void)
+{
+ auth_sasl_mech_register_module(&mech_gss_spnego);
+}
+#else
+void mech_gss_spnego_init(void);
+void mech_gss_spnego_deinit(void);
+
+void mech_gss_spnego_init(void)
+{
+ auth_sasl_mech_register_module(&mech_gss_spnego);
+}
+
+void mech_gss_spnego_deinit(void)
+{
+ auth_sasl_mech_unregister_module(&mech_gss_spnego);
+}
+#endif
+
+#endif
--- /dev/null
+/* Copyright (c) 2023 Dovecot authors, see the included COPYING file */
+
+#include "auth-common.h"
+#include "sasl-server.h"
+#include "sasl-server-gssapi.h"
+#include "auth-sasl.h"
+#include "auth-sasl-gssapi.h"
+
+static bool
+mech_gssapi_register(struct sasl_server_instance *sasl_inst,
+ const struct auth_settings *set ATTR_UNUSED)
+{
+ sasl_server_mech_register_gssapi(sasl_inst);
+ return TRUE;
+}
+
+static void
+mech_gssapi_unregister(struct sasl_server_instance *sasl_inst)
+{
+ sasl_server_mech_unregister_gssapi(sasl_inst);
+}
+
+static struct auth_sasl_mech_module mech_gssapi = {
+ .mech_name = SASL_MECH_NAME_GSSAPI,
+
+ .mech_register = mech_gssapi_register,
+ .mech_unregister = mech_gssapi_unregister,
+};
+
+#ifdef BUILTIN_GSSAPI
+void auth_sasl_mech_gssapi_register(void)
+{
+ auth_sasl_mech_register_module(&mech_gssapi);
+}
+#else
+void mech_gssapi_init(void);
+void mech_gssapi_deinit(void);
+
+void mech_gssapi_init(void)
+{
+ auth_sasl_mech_register_module(&mech_gssapi);
+}
+
+void mech_gssapi_deinit(void)
+{
+ auth_sasl_mech_unregister_module(&mech_gssapi);
+}
+#endif
#include "auth-sasl-oauth2.h"
+/*
+ * Token verification
+ */
+
static void
oauth2_verify_finish(enum passdb_result result,
struct auth_request *auth_request)
#include "lib.h"
#include "str.h"
#include "settings-parser.h"
-#include "sasl-server-protected.h" // FIXME: remove
+#include "llist.h"
+#include "sasl-server.h"
#include "auth.h"
#include "auth-common.h"
#include "auth-sasl.h"
+#include "auth-sasl-gssapi.h"
#include "auth-sasl-oauth2.h"
#include "auth-request.h"
#include "auth-request-handler.h"
*/
struct auth_sasl_mech_module_list {
- struct auth_sasl_mech_module_list *next;
+ struct auth_sasl_mech_module_list *prev, *next;
- struct auth_sasl_mech_module module;
+ const struct auth_sasl_mech_module *module;
+
+ bool mech_registered:1;
};
-static struct auth_sasl_mech_module_list *auth_sasl_mech_modules;
+static struct auth_sasl_mech_module_list *mech_modules = NULL;
+static struct auth_sasl_mech_module_list *mech_modules_loaded_head = NULL;
+static struct auth_sasl_mech_module_list *mech_modules_loaded_tail = NULL;
+
+const struct auth_sasl_mech_module *
+auth_sasl_mech_module_find(const char *name)
+{
+ struct auth_sasl_mech_module_list *list;
+
+ name = t_str_ucase(name);
+ for (list = mech_modules; list != NULL; list = list->next) {
+ if (strcmp(list->module->mech_name, name) == 0)
+ return list->module;
+ }
+ return NULL;
+}
void auth_sasl_mech_register_module(
const struct auth_sasl_mech_module *module)
{
+ const struct auth_sasl_mech_module *existing;
struct auth_sasl_mech_module_list *list;
i_assert(strcmp(module->mech_name,
t_str_ucase(module->mech_name)) == 0);
+ existing = auth_sasl_mech_module_find(module->mech_name);
+ if (existing != NULL) {
+ i_assert(existing == module);
+ return;
+ }
+
list = i_new(struct auth_sasl_mech_module_list, 1);
- list->module = *module;
+ list->module = module;
- list->next = auth_sasl_mech_modules;
- auth_sasl_mech_modules = list;
+ DLLIST_PREPEND(&mech_modules, list);
}
void auth_sasl_mech_unregister_module(
const struct auth_sasl_mech_module *module)
{
- struct auth_sasl_mech_module_list **pos, *list;
+ struct auth_sasl_mech_module_list *list;
- for (pos = &auth_sasl_mech_modules; *pos != NULL; pos = &(*pos)->next) {
- if (strcmp((*pos)->module.mech_name, module->mech_name) == 0) {
- list = *pos;
- *pos = (*pos)->next;
- i_free(list);
- break;
- }
+ for (list = mech_modules; list != NULL; list = list->next) {
+ if (list->module != module)
+ continue;
+
+ DLLIST_REMOVE(&mech_modules, list);
+ i_free(list);
+ break;
}
}
-const struct auth_sasl_mech_module *
-auth_sasl_mech_module_find(const char *name)
+static void
+auth_sasl_mech_module_add_loaded(const struct auth_sasl_mech_module *module)
+{
+ struct auth_sasl_mech_module_list *list;
+
+ for (list = mech_modules_loaded_head; list != NULL; list = list->next) {
+ if (list->module == module)
+ return;
+ }
+
+ list = i_new(struct auth_sasl_mech_module_list, 1);
+ list->module = module;
+
+ DLLIST2_APPEND(&mech_modules_loaded_head, &mech_modules_loaded_tail,
+ list);
+}
+
+static bool auth_sasl_mech_module_load(const char *name)
{
struct auth_sasl_mech_module_list *list;
+
name = t_str_ucase(name);
+ for (list = mech_modules; list != NULL; list = list->next) {
+ if (strcmp(list->module->mech_name, name) == 0) {
+ auth_sasl_mech_module_add_loaded(list->module);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
- for (list = auth_sasl_mech_modules; list != NULL; list = list->next) {
- if (strcmp(list->module.mech_name, name) == 0)
- return &list->module;
+static void auth_sasl_mechs_deinit(void)
+{
+ struct auth_sasl_mech_module_list *list, *list_next;
+
+ list = mech_modules;
+ while (list != NULL) {
+ list_next = list->next;
+
+ i_free(list);
+ list = list_next;
}
- return NULL;
+
+ list = mech_modules_loaded_head;
+ while (list != NULL) {
+ list_next = list->next;
+
+ i_free(list);
+ list = list_next;
+ }
+}
+
+/*
+ * Built-in Mechanisms
+ */
+
+#define MECH_SIMPLE_REGISTER__TEMPLATE(mech) \
+static bool \
+mech_ ## mech ## _register(struct sasl_server_instance *sasl_inst, \
+ const struct auth_settings *set ATTR_UNUSED) \
+{ \
+ sasl_server_mech_register_ ## mech(sasl_inst); \
+ return TRUE; \
+}
+
+MECH_SIMPLE_REGISTER__TEMPLATE(anonymous)
+MECH_SIMPLE_REGISTER__TEMPLATE(cram_md5)
+MECH_SIMPLE_REGISTER__TEMPLATE(digest_md5)
+MECH_SIMPLE_REGISTER__TEMPLATE(external)
+MECH_SIMPLE_REGISTER__TEMPLATE(login)
+MECH_SIMPLE_REGISTER__TEMPLATE(oauthbearer)
+MECH_SIMPLE_REGISTER__TEMPLATE(xoauth2)
+MECH_SIMPLE_REGISTER__TEMPLATE(otp)
+MECH_SIMPLE_REGISTER__TEMPLATE(plain)
+MECH_SIMPLE_REGISTER__TEMPLATE(scram_sha1)
+MECH_SIMPLE_REGISTER__TEMPLATE(scram_sha1_plus)
+MECH_SIMPLE_REGISTER__TEMPLATE(scram_sha256)
+MECH_SIMPLE_REGISTER__TEMPLATE(scram_sha256_plus)
+
+static bool
+mech_winbind_ntlm_register(struct sasl_server_instance *sasl_inst,
+ const struct auth_settings *set ATTR_UNUSED)
+{
+ sasl_server_mech_register_winbind_ntlm(sasl_inst);
+ return TRUE;
+}
+
+static bool
+mech_winbind_gss_spnego_register(struct sasl_server_instance *sasl_inst,
+ const struct auth_settings *set ATTR_UNUSED)
+{
+ sasl_server_mech_register_winbind_gss_spnego(sasl_inst);
+ return TRUE;
+}
+
+static bool
+mech_apop_register(struct sasl_server_instance *sasl_inst,
+ const struct auth_settings *set ATTR_UNUSED)
+{
+ auth_sasl_mech_register_apop(sasl_inst);
+ return TRUE;
+}
+
+static const struct auth_sasl_mech_module mech_anonymous = {
+ .mech_name = SASL_MECH_NAME_ANONYMOUS,
+
+ .mech_register = mech_anonymous_register,
+};
+
+static const struct auth_sasl_mech_module mech_cram_md5 = {
+ .mech_name = SASL_MECH_NAME_CRAM_MD5,
+
+ .mech_register = mech_cram_md5_register,
+};
+
+static const struct auth_sasl_mech_module mech_digest_md5 = {
+ .mech_name = SASL_MECH_NAME_DIGEST_MD5,
+
+ .mech_register = mech_digest_md5_register,
+};
+
+static const struct auth_sasl_mech_module mech_external = {
+ .mech_name = SASL_MECH_NAME_EXTERNAL,
+
+ .mech_register = mech_external_register,
+};
+
+static const struct auth_sasl_mech_module mech_login = {
+ .mech_name = SASL_MECH_NAME_LOGIN,
+
+ .mech_register = mech_login_register,
+};
+
+static const struct auth_sasl_mech_module mech_oauthbearer = {
+ .mech_name = SASL_MECH_NAME_OAUTHBEARER,
+
+ .mech_register = mech_oauthbearer_register,
+};
+
+static const struct auth_sasl_mech_module mech_otp = {
+ .mech_name = SASL_MECH_NAME_OTP,
+
+ .mech_register = mech_otp_register,
+};
+
+static const struct auth_sasl_mech_module mech_plain = {
+ .mech_name = SASL_MECH_NAME_PLAIN,
+
+ .mech_register = mech_plain_register,
+};
+
+static const struct auth_sasl_mech_module mech_scram_sha1 = {
+ .mech_name = SASL_MECH_NAME_SCRAM_SHA_1,
+
+ .mech_register = mech_scram_sha1_register,
+};
+
+static const struct auth_sasl_mech_module mech_scram_sha1_plus = {
+ .mech_name = SASL_MECH_NAME_SCRAM_SHA_1_PLUS,
+
+ .mech_register = mech_scram_sha1_plus_register,
+};
+
+static const struct auth_sasl_mech_module mech_scram_sha256 = {
+ .mech_name = SASL_MECH_NAME_SCRAM_SHA_256,
+
+ .mech_register = mech_scram_sha256_register,
+};
+
+static const struct auth_sasl_mech_module mech_scram_sha256_plus = {
+ .mech_name = SASL_MECH_NAME_SCRAM_SHA_256_PLUS,
+
+ .mech_register = mech_scram_sha256_plus_register,
+};
+
+static const struct auth_sasl_mech_module mech_winbind_ntlm = {
+ .mech_name = SASL_MECH_NAME_NTLM,
+
+ .mech_register = mech_winbind_ntlm_register,
+};
+
+static const struct auth_sasl_mech_module mech_winbind_gss_spnego = {
+ .mech_name = SASL_MECH_NAME_GSS_SPNEGO,
+
+ .mech_register = mech_winbind_gss_spnego_register,
+};
+
+static const struct auth_sasl_mech_module mech_xoauth2 = {
+ .mech_name = SASL_MECH_NAME_XOAUTH2,
+
+ .mech_register = mech_xoauth2_register,
+};
+
+static const struct auth_sasl_mech_module mech_apop = {
+ .mech_name = AUTH_SASL_MECH_NAME_APOP,
+
+ .mech_register = mech_apop_register,
+};
+
+static void auth_sasl_mechs_init(const struct auth_settings *set)
+{
+ auth_sasl_mech_register_module(&mech_anonymous);
+ auth_sasl_mech_register_module(&mech_cram_md5);
+ auth_sasl_mech_register_module(&mech_digest_md5);
+ auth_sasl_mech_register_module(&mech_external);
+#ifdef BUILTIN_GSSAPI
+ auth_sasl_mech_gssapi_register();
+#endif
+ if (set->use_winbind)
+ auth_sasl_mech_register_module(&mech_winbind_gss_spnego);
+#ifdef BUILTIN_GSSAPI
+ else
+ auth_sasl_mech_gss_spnego_register();
+#endif
+ auth_sasl_mech_register_module(&mech_login);
+ if (set->use_winbind)
+ auth_sasl_mech_register_module(&mech_winbind_ntlm);
+ auth_sasl_mech_register_module(&mech_oauthbearer);
+ auth_sasl_mech_register_module(&mech_otp);
+ auth_sasl_mech_register_module(&mech_plain);
+ auth_sasl_mech_register_module(&mech_scram_sha1);
+ auth_sasl_mech_register_module(&mech_scram_sha1_plus);
+ auth_sasl_mech_register_module(&mech_scram_sha256);
+ auth_sasl_mech_register_module(&mech_scram_sha256_plus);
+ auth_sasl_mech_register_module(&mech_xoauth2);
+
+ auth_sasl_mech_register_module(&mech_apop);
}
const char *auth_sasl_mechs_get_handshake(void)
* Instance
*/
-static const char *auth_sasl_mech_get_plugin_name(const char *name);
-
void auth_sasl_instance_init(struct auth *auth,
const struct auth_settings *set)
{
auth->sasl_inst =
sasl_server_instance_create(auth_sasl_server, &sasl_set);
- const struct sasl_server_mech_def *mech;
- const char *name;
-
- if (array_is_empty(&set->mechanisms))
- i_fatal("No authentication mechanisms configured");
+ struct auth_sasl_mech_module_list *list;
- array_foreach_elem(&set->mechanisms, name) {
- name = t_str_ucase(name);
+ for (list = mech_modules_loaded_head; list != NULL;
+ list = list->next) {
+ const struct auth_sasl_mech_module *mech = list->module;
- if (strcmp(name, SASL_MECH_NAME_ANONYMOUS) == 0) {
- if (*set->anonymous_username == '\0') {
- i_fatal("ANONYMOUS listed in mechanisms, "
- "but anonymous_username not set");
- }
- }
- mech = mech_module_find(name);
- if (mech == NULL) {
- /* maybe it's a plugin. try to load it. */
- auth_module_load(auth_sasl_mech_get_plugin_name(name));
- mech = mech_module_find(name);
- }
- if (mech == NULL)
- i_fatal("Unknown authentication mechanism '%s'", name);
- sasl_server_mech_register(auth->sasl_inst, mech);
+ list->mech_registered =
+ mech->mech_register(auth->sasl_inst, set);
}
auth->sasl_mech_dovecot_token =
- sasl_server_mech_register(auth->sasl_inst, &mech_dovecot_token);
+ auth_sasl_mech_register_dovecot_token(auth->sasl_inst);
}
static bool
void auth_sasl_instance_deinit(struct auth *auth)
{
+ struct auth_sasl_mech_module_list *list;
+
+ for (list = mech_modules_loaded_head; list != NULL;
+ list = list->next) {
+ const struct auth_sasl_mech_module *mech = list->module;
+
+ if (list->mech_registered && mech->mech_unregister != NULL)
+ mech->mech_unregister(auth->sasl_inst);
+ }
+
sasl_server_instance_unref(&auth->sasl_inst);
}
return str_c(str);
}
-void auth_sasl_preinit(void)
+void auth_sasl_preinit(const struct auth_settings *set)
{
auth_sasl_oauth2_initialize();
auth_sasl_server = sasl_server_init(auth_event,
&auth_sasl_request_funcs);
+
+ auth_sasl_mechs_init(set);
+
+ const char *name;
+
+ if (array_is_empty(&set->mechanisms))
+ i_fatal("No authentication mechanisms configured");
+
+ array_foreach_elem(&set->mechanisms, name) {
+ name = t_str_ucase(name);
+
+ if (strcmp(name, SASL_MECH_NAME_ANONYMOUS) == 0) {
+ if (*set->anonymous_username == '\0') {
+ i_fatal("ANONYMOUS listed in mechanisms, "
+ "but anonymous_username not set");
+ }
+ }
+ if (!auth_sasl_mech_module_load(name)) {
+ /* maybe it's a plugin. try to load it. */
+ auth_module_load(auth_sasl_mech_get_plugin_name(name));
+ }
+ if (!auth_sasl_mech_module_load(name))
+ i_fatal("Unknown authentication mechanism '%s'", name);
+ }
+
+ if (mech_modules_loaded_head == NULL)
+ i_fatal("No authentication mechanisms configured");
}
void auth_sasl_init(void)
void auth_sasl_deinit(void)
{
sasl_server_deinit(&auth_sasl_server);
+ auth_sasl_mechs_deinit();
auth_sasl_mechs_handshake_deinit();
}
struct auth_sasl_mech_module {
const char *mech_name;
+
+ bool (*mech_register)(struct sasl_server_instance *sasl_inst,
+ const struct auth_settings *set);
+ void (*mech_unregister)(struct sasl_server_instance *sasl_inst);
};
/*
* Mechanisms
*/
+void auth_sasl_mech_register_apop(struct sasl_server_instance *sinst);
+const struct sasl_server_mech *
+auth_sasl_mech_register_dovecot_token(struct sasl_server_instance *sinst);
+
void auth_sasl_mech_register_module(
const struct auth_sasl_mech_module *module);
void auth_sasl_mech_unregister_module(
* Global
*/
-void auth_sasl_preinit(void);
+void auth_sasl_preinit(const struct auth_settings *set);
void auth_sasl_init(void);
void auth_sasl_deinit(void);
#include "dict.h"
#include "password-scheme.h"
#include "passdb-cache.h"
-#include "sasl-server-protected.h"
+#include "sasl-server.h"
#include "otp.h"
#include "mech-otp.h"
#include "auth.h"
auth_penalty = auth_penalty_init(AUTH_PENALTY_ANVIL_PATH);
dict_drivers_register_builtin();
- auth_sasl_preinit();
+ auth_sasl_preinit(global_auth_settings);
auths_preinit(NULL, global_auth_settings, protocols);
listeners_init();
auths_free();
mech_otp_deinit();
- mech_deinit(global_auth_settings);
/* allow modules to unregister their dbs/drivers/etc. before freeing
the whole data structures containing them. */
+++ /dev/null
-/* Copyright (c) 2002-2018 Dovecot authors, see the included COPYING file */
-
-#include "auth-common.h"
-#include "ioloop.h"
-#include "str.h"
-#include "strfuncs.h"
-#include "passdb.h"
-
-#include "sasl-server-private.h"
-
-#include <ctype.h>
-
-static struct mech_module_list *mech_modules;
-
-void mech_register_module(const struct sasl_server_mech_def *module)
-{
- struct mech_module_list *list;
- i_assert(strcmp(module->name, t_str_ucase(module->name)) == 0);
-
- list = i_new(struct mech_module_list, 1);
- list->module = module;
-
- list->next = mech_modules;
- mech_modules = list;
-}
-
-void mech_unregister_module(const struct sasl_server_mech_def *module)
-{
- struct mech_module_list **pos, *list;
-
- for (pos = &mech_modules; *pos != NULL; pos = &(*pos)->next) {
- if (strcmp((*pos)->module->name, module->name) == 0) {
- list = *pos;
- *pos = (*pos)->next;
- i_free(list);
- break;
- }
- }
-}
-
-const struct sasl_server_mech_def *mech_module_find(const char *name)
-{
- struct mech_module_list *list;
- name = t_str_ucase(name);
-
- for (list = mech_modules; list != NULL; list = list->next) {
- if (strcmp(list->module->name, name) == 0)
- return list->module;
- }
- return NULL;
-}
-
-extern const struct sasl_server_mech_def mech_plain;
-extern const struct sasl_server_mech_def mech_login;
-extern const struct sasl_server_mech_def mech_apop;
-extern const struct sasl_server_mech_def mech_cram_md5;
-extern const struct sasl_server_mech_def mech_digest_md5;
-extern const struct sasl_server_mech_def mech_external;
-extern const struct sasl_server_mech_def mech_otp;
-extern const struct sasl_server_mech_def mech_scram_sha1;
-extern const struct sasl_server_mech_def mech_scram_sha1_plus;
-extern const struct sasl_server_mech_def mech_scram_sha256;
-extern const struct sasl_server_mech_def mech_scram_sha256_plus;
-extern const struct sasl_server_mech_def mech_anonymous;
-#ifdef HAVE_GSSAPI
-extern const struct sasl_server_mech_def mech_gssapi;
-#endif
-#ifdef HAVE_GSSAPI_SPNEGO
-extern const struct sasl_server_mech_def mech_gssapi_spnego;
-#endif
-extern const struct sasl_server_mech_def mech_winbind_ntlm;
-extern const struct sasl_server_mech_def mech_winbind_spnego;
-extern const struct sasl_server_mech_def mech_oauthbearer;
-extern const struct sasl_server_mech_def mech_xoauth2;
-
-void mech_init(const struct auth_settings *set)
-{
- mech_register_module(&mech_plain);
- mech_register_module(&mech_login);
- mech_register_module(&mech_apop);
- mech_register_module(&mech_cram_md5);
- mech_register_module(&mech_digest_md5);
- mech_register_module(&mech_external);
- if (set->use_winbind) {
- mech_register_module(&mech_winbind_ntlm);
- mech_register_module(&mech_winbind_spnego);
- } else {
-#if defined(HAVE_GSSAPI_SPNEGO) && defined(BUILTIN_GSSAPI)
- mech_register_module(&mech_gssapi_spnego);
-#endif
- }
- mech_register_module(&mech_otp);
- mech_register_module(&mech_scram_sha1);
- mech_register_module(&mech_scram_sha1_plus);
- mech_register_module(&mech_scram_sha256);
- mech_register_module(&mech_scram_sha256_plus);
- mech_register_module(&mech_anonymous);
-#ifdef BUILTIN_GSSAPI
- mech_register_module(&mech_gssapi);
-#endif
- mech_register_module(&mech_oauthbearer);
- mech_register_module(&mech_xoauth2);
-}
-
-void mech_deinit(const struct auth_settings *set)
-{
- mech_unregister_module(&mech_plain);
- mech_unregister_module(&mech_login);
- mech_unregister_module(&mech_apop);
- mech_unregister_module(&mech_cram_md5);
- mech_unregister_module(&mech_digest_md5);
- mech_unregister_module(&mech_external);
- if (set->use_winbind) {
- mech_unregister_module(&mech_winbind_ntlm);
- mech_unregister_module(&mech_winbind_spnego);
- } else {
-#if defined(HAVE_GSSAPI_SPNEGO) && defined(BUILTIN_GSSAPI)
- mech_unregister_module(&mech_gssapi_spnego);
-#endif
- }
- mech_unregister_module(&mech_otp);
- mech_unregister_module(&mech_scram_sha1);
- mech_unregister_module(&mech_scram_sha1_plus);
- mech_unregister_module(&mech_scram_sha256);
- mech_unregister_module(&mech_scram_sha256_plus);
- mech_unregister_module(&mech_anonymous);
-#ifdef BUILTIN_GSSAPI
- mech_unregister_module(&mech_gssapi);
-#endif
- mech_unregister_module(&mech_oauthbearer);
- mech_unregister_module(&mech_xoauth2);
-}
--- /dev/null
+#ifndef SASL_SERVER_GSSAPI_H
+#define SASL_SERVER_GSSAPI_H
+
+void sasl_server_mech_register_gssapi(struct sasl_server_instance *sinst);
+void sasl_server_mech_unregister_gssapi(struct sasl_server_instance *sinst);
+
+void sasl_server_mech_register_gss_spnego(struct sasl_server_instance *sinst);
+void sasl_server_mech_unregister_gss_spnego(struct sasl_server_instance *sinst);
+
+#endif
.auth_continue = mech_anonymous_auth_continue,
};
-const struct sasl_server_mech_def mech_anonymous = {
+static const struct sasl_server_mech_def mech_anonymous = {
.name = SASL_MECH_NAME_ANONYMOUS,
.flags = SASL_MECH_SEC_ANONYMOUS | SASL_MECH_SEC_ALLOW_NULS,
.funcs = &mech_anonymous_funcs,
};
+
+void sasl_server_mech_register_anonymous(struct sasl_server_instance *sinst)
+{
+ sasl_server_mech_register(sinst, &mech_anonymous);
+}
.auth_continue = mech_cram_md5_auth_continue,
};
-const struct sasl_server_mech_def mech_cram_md5 = {
+static const struct sasl_server_mech_def mech_cram_md5 = {
.name = SASL_MECH_NAME_CRAM_MD5,
.flags = SASL_MECH_SEC_DICTIONARY | SASL_MECH_SEC_ACTIVE,
.funcs = &mech_cram_md5_funcs,
};
+
+void sasl_server_mech_register_cram_md5(struct sasl_server_instance *sinst)
+{
+ sasl_server_mech_register(sinst, &mech_cram_md5);
+}
.auth_continue = mech_digest_md5_auth_continue,
};
-const struct sasl_server_mech_def mech_digest_md5 = {
+static const struct sasl_server_mech_def mech_digest_md5 = {
.name = SASL_MECH_NAME_DIGEST_MD5,
.flags = SASL_MECH_SEC_DICTIONARY | SASL_MECH_SEC_ACTIVE |
.funcs = &mech_digest_md5_funcs,
};
+void sasl_server_mech_register_digest_md5(struct sasl_server_instance *sinst)
+{
+ sasl_server_mech_register(sinst, &mech_digest_md5);
+}
+
void mech_digest_test_set_nonce(struct auth_request *auth_request,
const char *nonce)
{
.auth_continue = mech_external_auth_continue,
};
-const struct sasl_server_mech_def mech_external = {
+static const struct sasl_server_mech_def mech_external = {
.name = SASL_MECH_NAME_EXTERNAL,
.flags = 0,
.funcs = &mech_external_funcs,
};
+
+void sasl_server_mech_register_external(struct sasl_server_instance *sinst)
+{
+ sasl_server_mech_register(sinst, &mech_external);
+}
#include "safe-memset.h"
#include "sasl-server-protected.h"
+#include "sasl-server-gssapi.h"
#if defined(BUILTIN_GSSAPI) || defined(PLUGIN_BUILD)
.auth_free = mech_gssapi_auth_free,
};
-const struct sasl_server_mech_def mech_gssapi = {
+static const struct sasl_server_mech_def mech_gssapi = {
.name = SASL_MECH_NAME_GSSAPI,
.flags = SASL_MECH_SEC_ALLOW_NULS,
/* MIT Kerberos v1.5+ and Heimdal v0.7+ support SPNEGO for Kerberos tickets
internally. Nothing else needs to be done here. Note, however, that this does
not support SPNEGO when the only available credential is NTLM. */
-const struct sasl_server_mech_def mech_gssapi_spnego = {
+static const struct sasl_server_mech_def mech_gss_spnego = {
.name = SASL_MECH_NAME_GSS_SPNEGO,
.flags = SASL_MECH_SEC_ALLOW_NULS,
}
}
-#ifndef BUILTIN_GSSAPI
-void mech_gssapi_init(void);
-void mech_gssapi_deinit(void);
+void sasl_server_mech_register_gssapi(struct sasl_server_instance *sinst)
+{
+ sasl_server_mech_register(sinst, &mech_gssapi);
+}
-void mech_gssapi_init(void)
+void sasl_server_mech_unregister_gssapi(struct sasl_server_instance *sinst)
{
- mech_register_module(&mech_gssapi);
-#ifdef HAVE_GSSAPI_SPNEGO
- /* load if we already didn't load it using winbind */
- if (mech_module_find(mech_gssapi_spnego.name) == NULL)
- mech_register_module(&mech_gssapi_spnego);
-#endif
+ sasl_server_mech_unregister(sinst, &mech_gssapi);
}
-void mech_gssapi_deinit(void)
+void sasl_server_mech_register_gss_spnego(struct sasl_server_instance *sinst)
{
-#ifdef HAVE_GSSAPI_SPNEGO
- const struct sasl_server_mech_def *mech;
+ sasl_server_mech_register(sinst, &mech_gss_spnego);
+}
- mech = mech_module_find(mech_gssapi_spnego.name);
- if (mech != NULL && mech == &mech_gssapi_spnego)
- mech_unregister_module(&mech_gssapi_spnego);
-#endif
- mech_unregister_module(&mech_gssapi);
+void sasl_server_mech_unregister_gss_spnego(struct sasl_server_instance *sinst)
+{
+ sasl_server_mech_unregister(sinst, &mech_gss_spnego);
}
-#endif
#endif
.auth_continue = mech_login_auth_continue,
};
-const struct sasl_server_mech_def mech_login = {
+static const struct sasl_server_mech_def mech_login = {
.name = SASL_MECH_NAME_LOGIN,
.flags = SASL_MECH_SEC_PLAINTEXT,
.funcs = &mech_login_funcs,
};
+
+void sasl_server_mech_register_login(struct sasl_server_instance *sinst)
+{
+ sasl_server_mech_register(sinst, &mech_login);
+}
bool verifying_token:1;
};
-const struct sasl_server_mech_def mech_oauthbearer;
-const struct sasl_server_mech_def mech_xoauth2;
+static const struct sasl_server_mech_def mech_oauthbearer;
+static const struct sasl_server_mech_def mech_xoauth2;
static struct db_oauth2 *db_oauth2 = NULL;
.auth_continue = mech_oauthbearer_auth_continue,
};
-const struct sasl_server_mech_def mech_oauthbearer = {
+static const struct sasl_server_mech_def mech_oauthbearer = {
.name = SASL_MECH_NAME_OAUTHBEARER,
/* while this does not transfer plaintext password,
.auth_continue = mech_xoauth2_auth_continue,
};
-const struct sasl_server_mech_def mech_xoauth2 = {
+static const struct sasl_server_mech_def mech_xoauth2 = {
.name = SASL_MECH_NAME_XOAUTH2,
.flags = SASL_MECH_SEC_PLAINTEXT,
.funcs = &mech_xoauth2_funcs,
};
+
+void sasl_server_mech_register_oauthbearer(struct sasl_server_instance *sinst)
+{
+ sasl_server_mech_register(sinst, &mech_oauthbearer);
+}
+
+void sasl_server_mech_register_xoauth2(struct sasl_server_instance *sinst)
+{
+ sasl_server_mech_register(sinst, &mech_xoauth2);
+}
.auth_free = mech_otp_auth_free,
};
-const struct sasl_server_mech_def mech_otp = {
+static const struct sasl_server_mech_def mech_otp = {
.name = SASL_MECH_NAME_OTP,
.flags = SASL_MECH_SEC_DICTIONARY | SASL_MECH_SEC_ACTIVE |
{
otp_lock_deinit();
}
+
+void sasl_server_mech_register_otp(struct sasl_server_instance *sinst)
+{
+ sasl_server_mech_register(sinst, &mech_otp);
+}
.auth_continue = mech_plain_auth_continue,
};
-const struct sasl_server_mech_def mech_plain = {
+static const struct sasl_server_mech_def mech_plain = {
.name = SASL_MECH_NAME_PLAIN,
.flags = SASL_MECH_SEC_PLAINTEXT | SASL_MECH_SEC_ALLOW_NULS,
.funcs = &mech_plain_funcs,
};
+
+void sasl_server_mech_register_plain(struct sasl_server_instance *sinst)
+{
+ sasl_server_mech_register(sinst, &mech_plain);
+}
.auth_free = mech_scram_auth_free,
};
-const struct sasl_server_mech_def mech_scram_sha1 = {
+static const struct sasl_server_mech_def mech_scram_sha1 = {
.name = SASL_MECH_NAME_SCRAM_SHA_1,
.flags = SASL_MECH_SEC_MUTUAL_AUTH,
.funcs = &mech_scram_sha1_funcs,
};
-const struct sasl_server_mech_def mech_scram_sha1_plus = {
+static const struct sasl_server_mech_def mech_scram_sha1_plus = {
.name = SASL_MECH_NAME_SCRAM_SHA_1_PLUS,
.flags = SASL_MECH_SEC_MUTUAL_AUTH | SASL_MECH_SEC_CHANNEL_BINDING,
.auth_free = mech_scram_auth_free,
};
-const struct sasl_server_mech_def mech_scram_sha256 = {
+static const struct sasl_server_mech_def mech_scram_sha256 = {
.name = SASL_MECH_NAME_SCRAM_SHA_256,
.flags = SASL_MECH_SEC_MUTUAL_AUTH,
.funcs = &mech_scram_sha256_funcs,
};
-const struct sasl_server_mech_def mech_scram_sha256_plus = {
+static const struct sasl_server_mech_def mech_scram_sha256_plus = {
.name = SASL_MECH_NAME_SCRAM_SHA_256_PLUS,
.flags = SASL_MECH_SEC_MUTUAL_AUTH | SASL_MECH_SEC_CHANNEL_BINDING,
.funcs = &mech_scram_sha256_funcs,
};
+
+void sasl_server_mech_register_scram_sha1(
+ struct sasl_server_instance *sinst)
+{
+ sasl_server_mech_register(sinst, &mech_scram_sha1);
+}
+
+void sasl_server_mech_register_scram_sha1_plus(
+ struct sasl_server_instance *sinst)
+{
+ sasl_server_mech_register(sinst, &mech_scram_sha1_plus);
+}
+
+void sasl_server_mech_register_scram_sha256(
+ struct sasl_server_instance *sinst)
+{
+ sasl_server_mech_register(sinst, &mech_scram_sha256);
+}
+
+void sasl_server_mech_register_scram_sha256_plus(
+ struct sasl_server_instance *sinst)
+{
+ sasl_server_mech_register(sinst, &mech_scram_sha256_plus);
+}
}
static struct sasl_server_mech_request *
-mech_winbind_ntlm_auth_new(const struct sasl_server_mech *mech ATTR_UNUSED,
- pool_t pool)
+mech_winbind_ntlm_auth_new(
+ const struct sasl_server_mech *mech ATTR_UNUSED, pool_t pool)
{
return do_auth_new(pool, &winbind_ntlm_context);
}
static struct sasl_server_mech_request *
-mech_winbind_spnego_auth_new(const struct sasl_server_mech *mech ATTR_UNUSED,
- pool_t pool)
+mech_winbind_gss_spnego_auth_new(
+ const struct sasl_server_mech *mech ATTR_UNUSED, pool_t pool)
{
return do_auth_new(pool, &winbind_spnego_context);
}
-static const struct sasl_server_mech_funcs mech_winbind_ntlm_funcs = {
+static const struct sasl_server_mech_funcs mech_ntlm_funcs = {
.auth_new = mech_winbind_ntlm_auth_new,
.auth_initial = mech_winbind_auth_initial,
.auth_continue = mech_winbind_auth_continue,
};
-const struct sasl_server_mech_def mech_winbind_ntlm = {
+static const struct sasl_server_mech_def mech_ntlm = {
.name = SASL_MECH_NAME_NTLM,
.flags = SASL_MECH_SEC_DICTIONARY | SASL_MECH_SEC_ACTIVE |
SASL_MECH_SEC_ALLOW_NULS,
.passdb_need = SASL_MECH_PASSDB_NEED_NOTHING,
- .funcs = &mech_winbind_ntlm_funcs,
+ .funcs = &mech_ntlm_funcs,
};
-static const struct sasl_server_mech_funcs mech_winbind_spnego_funcs = {
- .auth_new = mech_winbind_spnego_auth_new,
+static const struct sasl_server_mech_funcs mech_gss_spnego_funcs = {
+ .auth_new = mech_winbind_gss_spnego_auth_new,
.auth_initial = mech_winbind_auth_initial,
.auth_continue = mech_winbind_auth_continue,
};
-const struct sasl_server_mech_def mech_winbind_spnego = {
+static const struct sasl_server_mech_def mech_gss_spnego = {
.name = SASL_MECH_NAME_GSS_SPNEGO,
.flags = SASL_MECH_SEC_ALLOW_NULS,
.passdb_need = SASL_MECH_PASSDB_NEED_NOTHING,
- .funcs = &mech_winbind_spnego_funcs,
+ .funcs = &mech_gss_spnego_funcs,
};
+
+void sasl_server_mech_register_winbind_ntlm(struct sasl_server_instance *sinst)
+{
+ sasl_server_mech_register(sinst, &mech_ntlm);
+}
+
+void sasl_server_mech_register_winbind_gss_spnego(
+ struct sasl_server_instance *sinst)
+{
+ sasl_server_mech_register(sinst, &mech_gss_spnego);
+}
const struct sasl_server_mech_funcs *funcs;
};
-struct mech_module_list {
- struct mech_module_list *next;
-
- const struct sasl_server_mech_def *module;
-};
-
-struct mechanisms_register {
- pool_t pool;
- const struct auth_settings *set;
-
- struct mech_module_list *modules;
- buffer_t *handshake;
- buffer_t *handshake_cbind;
-};
-
struct sasl_server_mech_data {
struct sasl_server *server;
pool_t pool;
* Mechanism
*/
-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);
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);
-
void sasl_server_mech_generic_auth_initial(
struct sasl_server_mech_request *mreq,
const unsigned char *data, size_t data_size);
-void mech_init(const struct auth_settings *set);
-void mech_deinit(const struct auth_settings *set);
-
/*
* Request
*/
void sasl_server_request_test_set_authid(struct sasl_server_req_ctx *rctx,
const char *authid);
+/*
+ * Mechanism definitions
+ */
+
+void sasl_server_mech_register_anonymous(struct sasl_server_instance *sinst);
+void sasl_server_mech_register_cram_md5(struct sasl_server_instance *sinst);
+void sasl_server_mech_register_digest_md5(struct sasl_server_instance *sinst);
+void sasl_server_mech_register_external(struct sasl_server_instance *sinst);
+void sasl_server_mech_register_login(struct sasl_server_instance *sinst);
+void sasl_server_mech_register_plain(struct sasl_server_instance *sinst);
+
+void sasl_server_mech_register_scram_sha1(
+ struct sasl_server_instance *sinst);
+void sasl_server_mech_register_scram_sha1_plus(
+ struct sasl_server_instance *sinst);
+void sasl_server_mech_register_scram_sha256(
+ struct sasl_server_instance *sinst);
+void sasl_server_mech_register_scram_sha256_plus(
+ struct sasl_server_instance *sinst);
+
+void sasl_server_mech_register_otp(struct sasl_server_instance *sinst);
+
+/* OAUTH2 */
+
+void sasl_server_mech_register_oauthbearer(struct sasl_server_instance *sinst);
+void sasl_server_mech_register_xoauth2(struct sasl_server_instance *sinst);
+
+/* Winbind */
+
+void sasl_server_mech_register_winbind_ntlm(
+ struct sasl_server_instance *sinst);
+void sasl_server_mech_register_winbind_gss_spnego(
+ struct sasl_server_instance *sinst);
+
/*
* Mechanism
*/
#include "auth-settings.h"
#include "auth-token.h"
#include "auth-penalty.h"
-#include "sasl-server-protected.h" // FIXME: remove
+#include "sasl-server.h"
#include "otp.h"
#include "mech-otp.h"
#include "db-oauth2.h"
&auth_setting_parser_info);
/* this is needed to get oauth2 initialized */
auth_event = simple_set.event;
- mech_init(global_auth_settings);
passdbs_init();
userdbs_init();
passdb_mock_mod_init();
password_schemes_register_all();
password_schemes_allow_weak(TRUE);
- auth_sasl_preinit();
+ auth_sasl_preinit(global_auth_settings);
auths_preinit(simple_set.event, global_auth_settings, protocols);
auths_init();
auth_token_init();
passdbs_deinit();
userdbs_deinit();
event_unref(&auth_event);
- mech_deinit(global_auth_settings);
auths_free();
auth_sasl_deinit();
settings_free(global_auth_settings);
#include "str.h"
#include "ioloop.h"
#include "master-service.h"
-#include "sasl-server-private.h" // FIXME: remove
#include "auth-common.h"
#include "auth-sasl.h"
#include "auth-request.h"