#include "randgen.h"
#include "master-service.h"
#include "sasl-server-protected.h" // FIXME: remove
+#include "auth-sasl.h"
#include "auth-request-handler.h"
#include "auth-client-interface.h"
#include "auth-client-connection.h"
mechanisms = t_strconcat("MECH\t",
mech_dovecot_token.name, "\tprivate\n", NULL);
} else {
- mechanisms = str_c(conn->auth->reg->handshake);
- if (conn->conn.minor_version >= AUTH_CLIENT_MINOR_VERSION_CHANNEL_BINDING) {
- mechanisms_cbind =
- str_c(conn->auth->reg->handshake_cbind);
- }
+ mechanisms = auth_sasl_mechs_get_handshake();
+ if (conn->conn.minor_version >= AUTH_CLIENT_MINOR_VERSION_CHANNEL_BINDING)
+ mechanisms_cbind = auth_sasl_mechs_get_handshake_cbind();
}
str = t_str_new(128);
static int
auth_request_handler_find_mech(struct auth_request_handler *handler,
+ struct auth_request *request,
const char *mech_name,
- const struct sasl_server_mech_def **mech_r)
+ const struct sasl_server_mech **mech_r)
{
- const struct sasl_server_mech_def *mech;
+ struct auth *auth = auth_request_get_auth(request);
+ const struct sasl_server_mech *mech;
if (handler->token_auth) {
- mech = &mech_dovecot_token;
- if (strcmp(mech_name, mech->name) == 0) {
+ mech = auth->sasl_mech_dovecot_token;
+ if (strcmp(sasl_server_mech_get_name(mech), mech_name) == 0) {
*mech_r = mech;
return 0;
}
return -1;
}
- struct auth *auth_default = auth_default_protocol();
-
- mech = mech_register_find(auth_default->reg, mech_name);
+ mech = sasl_server_mech_find(auth->sasl_inst, mech_name);
if (mech == NULL) {
/* unsupported mechanism */
e_error(handler->conn->conn.event,
return -1;
}
- const struct sasl_server_mech_def *mech;
+ const struct sasl_server_mech *mech;
- if (auth_request_handler_find_mech(handler, mech_name, &mech) < 0)
+ if (auth_request_handler_find_mech(handler, request, mech_name,
+ &mech) < 0)
return -1;
auth_request_init_sasl(request, mech);
auth_str_add_keyvalue(dest, "master_user",
request->fields.master_user);
}
- auth_str_add_keyvalue(dest, "auth_mech", request->mech->name);
+ auth_str_add_keyvalue(dest, "auth_mech", request->fields.mech_name);
if (*request->set->anonymous_username != '\0' &&
strcmp(request->fields.user, request->set->anonymous_username) == 0) {
/* this is an anonymous login, either via ANONYMOUS
}
void auth_request_init_sasl(struct auth_request *request,
- const struct sasl_server_mech_def *mech)
+ const struct sasl_server_mech *mech)
{
- request->mech = mech;
+ request->mech = mech->def;
const char *prefix = t_strconcat(
t_str_lcase(request->mech->name), ": ", NULL);
void auth_request_init(struct auth_request *request);
void auth_request_init_sasl(struct auth_request *request,
- const struct sasl_server_mech_def *mech);
+ const struct sasl_server_mech *mech);
struct auth *auth_request_get_auth(struct auth_request *request);
static struct sasl_server *auth_sasl_server;
+static char *auth_sasl_mechs_handshake;
+static char *auth_sasl_mechs_handshake_cbind;
+
/*
* Request
*/
}
void auth_sasl_request_init(struct auth_request *request,
- const struct sasl_server_mech_def *mech_def)
+ const struct sasl_server_mech *mech)
{
- struct auth *auth = auth_request_get_auth(request);
- const struct sasl_server_mech *mech;
-
- mech = sasl_server_mech_find(auth->sasl_inst, mech_def->name);
- if (mech == NULL)
- mech = sasl_server_mech_register(auth->sasl_inst, mech_def);
- i_assert(mech != NULL);
sasl_server_request_create(&request->sasl.req, mech,
auth_sasl_translate_protocol_name(request),
request->mech_event);
return NULL;
}
+const char *auth_sasl_mechs_get_handshake(void)
+{
+ return auth_sasl_mechs_handshake;
+}
+
+const char *auth_sasl_mechs_get_handshake_cbind(void)
+{
+ return auth_sasl_mechs_handshake_cbind;
+}
+
/*
* 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 char *mech_get_plugin_name(const char *name);
-void mech_register_add(struct mechanisms_register *reg,
- const struct sasl_server_mech_def *mech);
-
-struct mechanisms_register *
-mech_register_init(const struct auth_settings *set);
-struct mechanisms_register *
-mech_register_init(const struct auth_settings *set)
-{
- struct mechanisms_register *reg;
const struct sasl_server_mech_def *mech;
const char *name;
- pool_t pool;
-
- pool = pool_alloconly_create("mechanisms register", 1024);
- reg = p_new(pool, struct mechanisms_register, 1);
- reg->pool = pool;
- reg->set = set;
- reg->handshake = str_new(pool, 512);
- reg->handshake_cbind = str_new(pool, 256);
if (array_is_empty(&set->mechanisms))
i_fatal("No authentication mechanisms configured");
mech = mech_module_find(name);
if (mech == NULL) {
/* maybe it's a plugin. try to load it. */
- auth_module_load(mech_get_plugin_name(name));
+ 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);
- mech_register_add(reg, mech);
+ sasl_server_mech_register(auth->sasl_inst, mech);
}
- return reg;
+
+ auth->sasl_mech_dovecot_token =
+ sasl_server_mech_register(auth->sasl_inst, &mech_dovecot_token);
}
static bool
void auth_sasl_instance_verify(const struct auth *auth)
{
- const struct mech_module_list *list;
+ struct sasl_server_mech_iter *mech_iter;
- for (list = auth->reg->modules; list != NULL; list = list->next) {
- if (!auth_sasl_mech_verify_passdb(
- auth, list->module->passdb_need))
+ mech_iter = sasl_server_instance_mech_iter_new(auth->sasl_inst);
+ while (sasl_server_mech_iter_next(mech_iter)) {
+ if (!auth_sasl_mech_verify_passdb(auth, mech_iter->passdb_need))
break;
}
- if (list != NULL) {
+ if (!sasl_server_mech_iter_ended(mech_iter)) {
if (auth->passdbs == NULL) {
i_fatal("No passdbs specified in configuration file. "
"%s mechanism needs one",
- list->module->name);
+ mech_iter->name);
}
i_fatal("%s mechanism can't be supported with given passdbs",
- list->module->name);
+ mech_iter->name);
}
+
+ sasl_server_mech_iter_free(&mech_iter);
}
void auth_sasl_instance_deinit(struct auth *auth)
* Global
*/
-void mech_register_add(struct mechanisms_register *reg,
- const struct sasl_server_mech_def *mech)
-{
- struct mech_module_list *list;
- string_t *handshake;
-
- list = p_new(reg->pool, struct mech_module_list, 1);
- list->module = mech;
-
- if ((mech->flags & SASL_MECH_SEC_CHANNEL_BINDING) != 0)
- handshake = reg->handshake_cbind;
- else
- handshake = reg->handshake;
-
- str_printfa(handshake, "MECH\t%s", mech->name);
- if ((mech->flags & SASL_MECH_SEC_PRIVATE) != 0)
- str_append(handshake, "\tprivate");
- if ((mech->flags & SASL_MECH_SEC_ANONYMOUS) != 0)
- str_append(handshake, "\tanonymous");
- if ((mech->flags & SASL_MECH_SEC_PLAINTEXT) != 0)
- str_append(handshake, "\tplaintext");
- if ((mech->flags & SASL_MECH_SEC_DICTIONARY) != 0)
- str_append(handshake, "\tdictionary");
- if ((mech->flags & SASL_MECH_SEC_ACTIVE) != 0)
- str_append(handshake, "\tactive");
- if ((mech->flags & SASL_MECH_SEC_FORWARD_SECRECY) != 0)
- str_append(handshake, "\tforward-secrecy");
- if ((mech->flags & SASL_MECH_SEC_MUTUAL_AUTH) != 0)
- str_append(handshake, "\tmutual-auth");
- if ((mech->flags & SASL_MECH_SEC_CHANNEL_BINDING) != 0)
- str_append(handshake, "\tchannel-binding");
- str_append_c(handshake, '\n');
-
- list->next = reg->modules;
- reg->modules = list;
-}
-
-const char *mech_get_plugin_name(const char *name)
+static void auth_sasl_mechs_handshake_init(void)
+{
+ struct sasl_server_mech_iter *iter;
+ string_t *handshake_buf = t_str_new(512);
+ string_t *handshake_buf_cbind = t_str_new(256);
+
+ iter = sasl_server_mech_iter_new(auth_sasl_server);
+ while (sasl_server_mech_iter_next(iter)) {
+ string_t *handshake;
+
+ if ((iter->flags & SASL_MECH_SEC_CHANNEL_BINDING) != 0)
+ handshake = handshake_buf_cbind;
+ else
+ handshake = handshake_buf;
+
+ str_printfa(handshake, "MECH\t%s", iter->name);
+ if ((iter->flags & SASL_MECH_SEC_PRIVATE) != 0)
+ str_append(handshake, "\tprivate");
+ if ((iter->flags & SASL_MECH_SEC_ANONYMOUS) != 0)
+ str_append(handshake, "\tanonymous");
+ if ((iter->flags & SASL_MECH_SEC_PLAINTEXT) != 0)
+ str_append(handshake, "\tplaintext");
+ if ((iter->flags & SASL_MECH_SEC_DICTIONARY) != 0)
+ str_append(handshake, "\tdictionary");
+ if ((iter->flags & SASL_MECH_SEC_ACTIVE) != 0)
+ str_append(handshake, "\tactive");
+ if ((iter->flags & SASL_MECH_SEC_FORWARD_SECRECY) != 0)
+ str_append(handshake, "\tforward-secrecy");
+ if ((iter->flags & SASL_MECH_SEC_MUTUAL_AUTH) != 0)
+ str_append(handshake, "\tmutual-auth");
+ if ((iter->flags & SASL_MECH_SEC_CHANNEL_BINDING) != 0)
+ str_append(handshake, "\tchannel-binding");
+ str_append_c(handshake, '\n');
+ }
+ sasl_server_mech_iter_free(&iter);
+
+ auth_sasl_mechs_handshake = i_strdup(str_c(handshake_buf));
+ auth_sasl_mechs_handshake_cbind = i_strdup(str_c(handshake_buf_cbind));
+}
+
+static void auth_sasl_mechs_handshake_deinit(void)
+{
+ i_free(auth_sasl_mechs_handshake);
+ i_free(auth_sasl_mechs_handshake_cbind);
+}
+
+static const char *auth_sasl_mech_get_plugin_name(const char *name)
{
string_t *str = t_str_new(32);
void auth_sasl_init(void)
{
+ auth_sasl_mechs_handshake_init();
}
void auth_sasl_deinit(void)
{
sasl_server_deinit(&auth_sasl_server);
+ auth_sasl_mechs_handshake_deinit();
}
*/
void auth_sasl_request_init(struct auth_request *request,
- const struct sasl_server_mech_def *mech_def);
+ const struct sasl_server_mech *mech);
void auth_sasl_request_deinit(struct auth_request *request);
void auth_sasl_request_initial(struct auth_request *request);
const struct auth_sasl_mech_module *
auth_sasl_mech_module_find(const char *name);
+const char *auth_sasl_mechs_get_handshake(void);
+const char *auth_sasl_mechs_get_handshake_cbind(void);
+
/*
* Instance
*/
}
static struct auth * ATTR_NULL(2)
-auth_preinit(const struct auth_settings *set, const char *protocol,
- const struct mechanisms_register *reg)
+auth_preinit(const struct auth_settings *set, const char *protocol)
{
const struct auth_passdb_settings *const *passdbs;
const struct auth_userdb_settings *const *userdbs;
auth->protocol = p_strdup(pool, protocol);
auth->protocol_set = set;
pool_ref(set->pool);
- auth->reg = reg;
if (array_is_created(&set->parsed_passdbs))
passdbs = array_get(&set->parsed_passdbs, &db_count);
void auths_preinit(struct event *parent_event,
const struct auth_settings *set,
- const struct mechanisms_register *reg,
const char *const *protocols)
{
const struct auth_settings *protocol_set;
event_add_category(auth_event, &event_category_auth);
i_array_init(&auths, 8);
- auth = auth_preinit(set, NULL, reg);
+ auth = auth_preinit(set, NULL);
array_push_back(&auths, &auth);
for (i = 0; protocols[i] != NULL; i++) {
not_protocol = protocols[i];
}
protocol_set = auth_settings_get(protocols[i]);
- auth = auth_preinit(protocol_set, protocols[i], reg);
+ auth = auth_preinit(protocol_set, protocols[i]);
array_push_back(&auths, &auth);
settings_free(protocol_set);
}
const char *protocol;
const struct auth_settings *protocol_set;
- const struct mechanisms_register *reg;
struct sasl_server_instance *sasl_inst;
+ const struct sasl_server_mech *sasl_mech_dovecot_token;
struct auth_passdb *masterdbs;
struct auth_passdb *passdbs;
void auths_preinit(struct event *parent_event,
const struct auth_settings *set,
- const struct mechanisms_register *reg,
const char *const *protocols);
void auths_init(void);
void auths_deinit(void);
struct auth_penalty *auth_penalty;
static struct module *modules = NULL;
-static struct mechanisms_register *mech_reg;
static ARRAY(struct auth_socket_listener) listeners;
void auth_refresh_proctitle(void)
dict_drivers_register_builtin();
auth_sasl_preinit();
- auths_preinit(NULL, global_auth_settings, mech_reg, protocols);
+ auths_preinit(NULL, global_auth_settings, protocols);
listeners_init();
if (!worker)
/* there are no more auth requests */
auths_free();
- mech_register_deinit(&mech_reg);
mech_otp_deinit();
mech_deinit(global_auth_settings);
extern const struct sasl_server_mech_def mech_oauthbearer;
extern const struct sasl_server_mech_def mech_xoauth2;
-void mech_register_add(struct mechanisms_register *reg,
- const struct sasl_server_mech_def *mech);
-
-const char *mech_get_plugin_name(const char *name);
-
-struct mechanisms_register *
-mech_register_init(const struct auth_settings *set);
-
-void mech_register_deinit(struct mechanisms_register **_reg)
-{
- struct mechanisms_register *reg = *_reg;
-
- *_reg = NULL;
- pool_unref(®->pool);
-}
-
-const struct sasl_server_mech_def *
-mech_register_find(const struct mechanisms_register *reg, const char *name)
-{
- const struct mech_module_list *list;
- name = t_str_ucase(name);
-
- for (list = reg->modules; list != NULL; list = list->next) {
- if (strcmp(list->module->name, name) == 0)
- return list->module;
- }
- return NULL;
-}
-
void mech_init(const struct auth_settings *set)
{
mech_register_module(&mech_plain);
request->password_scheme = password_scheme;
struct auth *auth = auth_default_protocol();
+ struct sasl_server_instance *sinst = auth->sasl_inst;
struct auth_scram_server_settings scram_set;
i_zero(&scram_set);
scram_set.hash_method = hash_method;
- if (mech_register_find(auth->reg,
- t_strconcat(password_scheme,
- "-PLUS", NULL)) == NULL) {
+ if (sasl_server_mech_find(
+ sinst, t_strconcat(request->password_scheme,
+ "-PLUS", NULL)) == NULL) {
scram_set.cbind_support =
AUTH_SCRAM_CBIND_SERVER_SUPPORT_NONE;
- } else if (mech_register_find(auth->reg,
- request->password_scheme) == NULL) {
+ } else if (sasl_server_mech_find(sinst,
+ request->password_scheme) == NULL) {
scram_set.cbind_support =
AUTH_SCRAM_CBIND_SERVER_SUPPORT_REQUIRED;
} else {
struct sasl_server_mech_request *mreq,
const unsigned char *data, size_t data_size);
-struct mechanisms_register *
-mech_register_init(const struct auth_settings *set);
-void mech_register_deinit(struct mechanisms_register **reg);
-const struct sasl_server_mech_def *
-mech_register_find(const struct mechanisms_register *reg, const char *name);
-
void mech_init(const struct auth_settings *set);
void mech_deinit(const struct auth_settings *set);
#include "sasl-common.h"
struct sasl_passdb_result;
-struct sasl_server_mech_def;
struct sasl_server_mech;
struct sasl_server_request;
struct sasl_server_req_ctx;
static const char *const settings[] = {
"base_dir", ".",
- "auth_mechanisms", "plain xoauth2",
+ "auth_mechanisms",
+ "ANONYMOUS APOP CRAM-MD5 DIGEST-MD5 EXTERNAL LOGIN PLAIN OTP "
+ "OAUTHBEARER SCRAM-SHA-1 SCRAM-SHA-256 XOAUTH2",
"auth_username_chars", "",
"auth_username_format", "",
/* For tests of digest-md5. */
NULL
};
-static struct mechanisms_register *mech_reg;
static struct settings_simple simple_set;
void test_auth_init(void)
/* this is needed to get oauth2 initialized */
auth_event = simple_set.event;
mech_init(global_auth_settings);
- mech_reg = mech_register_init(global_auth_settings);
passdbs_init();
userdbs_init();
passdb_mock_mod_init();
password_schemes_allow_weak(TRUE);
auth_sasl_preinit();
- auths_preinit(simple_set.event, global_auth_settings, mech_reg, protocols);
+ auths_preinit(simple_set.event, global_auth_settings, protocols);
auths_init();
auth_token_init();
auth_sasl_init();
userdbs_deinit();
event_unref(&auth_event);
mech_deinit(global_auth_settings);
- mech_register_deinit(&mech_reg);
auths_free();
auth_sasl_deinit();
settings_free(global_auth_settings);
}
static void test_mech_prepare_request(struct auth_request **request_r,
- const struct sasl_server_mech_def *mech,
+ const char *mech_name,
struct auth_request_handler *handler,
unsigned int running_test,
const struct test_case *test_case)
request->mech_password = NULL;
request->fields.protocol = "service";
request->state = AUTH_REQUEST_STATE_NEW;
- request->mech = mech;
request->set = new_set;
request->protocol_set = global_auth_settings;
request->connect_uid = running_test;
handler->refcount = 1;
+ struct auth *auth = auth_default_protocol();
+ const struct sasl_server_mech *mech;
+ if (strcmp(mech_name, "DOVECOT-TOKEN") == 0)
+ mech = auth->sasl_mech_dovecot_token;
+ else
+ mech = sasl_server_mech_find(auth->sasl_inst, mech_name);
+ i_assert(mech != NULL);
+ request->mech = mech->def;
+
auth_request_init_sasl(request, mech);
request->failure_nodelay = TRUE;
N_ELEMENTS(tests));
test_begin(testname);
- test_mech_prepare_request(&request, mech, &handler,
+ test_mech_prepare_request(&request, mech->name, &handler,
running_test, test_case);
if (mech == &mech_apop && test_case->in == NULL) {