#include "auth-request.h"
#include "auth-request-handler.h"
-struct sasl_server *auth_sasl_server;
+static struct sasl_server *auth_sasl_server;
/*
* Request
void auth_sasl_request_init(struct auth_request *request,
const struct sasl_server_mech_def *mech)
{
- sasl_server_request_create(&request->sasl.req, auth_sasl_server, mech,
+ struct auth *auth = auth_request_get_auth(request);
+
+ sasl_server_request_create(&request->sasl.req, auth->sasl_inst, mech,
auth_sasl_translate_protocol_name(request),
request->mech_event);
}
return NULL;
}
+/*
+ * Instance
+ */
+
+void auth_sasl_instance_init(struct auth *auth)
+{
+ const struct sasl_server_settings sasl_set = {
+ .event_parent = auth_event,
+ };
+
+ auth->sasl_inst =
+ sasl_server_instance_create(auth_sasl_server, &sasl_set);
+}
+
+void auth_sasl_instance_deinit(struct auth *auth)
+{
+ sasl_server_instance_unref(&auth->sasl_inst);
+}
+
/*
* Global
*/
#define AUTH_SASL_MAX_MECH_NAME_LEN 64
struct auth_request;
+struct auth_settings;
struct auth_sasl_mech_module {
const char *mech_name;
};
-extern struct sasl_server *auth_sasl_server;
-
/*
* Request
*/
const struct auth_sasl_mech_module *
auth_sasl_mech_module_find(const char *name);
+/*
+ * Instance
+ */
+
+void auth_sasl_instance_init(struct auth *auth);
+void auth_sasl_instance_deinit(struct auth *auth);
+
/*
* Global
*/
#include "userdb.h"
#include "passdb.h"
#include "auth.h"
+#include "auth-sasl.h"
#include "dns-lookup.h"
#define AUTH_DNS_IDLE_TIMEOUT_MSECS (1000*60)
/* use a dummy userdb static. */
auth_userdb_preinit(auth, &userdb_dummy_set);
}
+
+ auth_sasl_instance_init(auth);
+
return auth;
}
static void auth_free(struct auth *auth)
{
+ auth_sasl_instance_deinit(auth);
settings_free(auth->protocol_set);
pool_unref(&auth->pool);
}
#define PASSWORD_HIDDEN_STR "<hidden>"
+struct sasl_server_instance;
+
ARRAY_DEFINE_TYPE(auth, struct auth *);
extern ARRAY_TYPE(auth) auths;
const struct auth_settings *protocol_set;
const struct mechanisms_register *reg;
+ struct sasl_server_instance *sasl_inst;
+
struct auth_passdb *masterdbs;
struct auth_passdb *passdbs;
struct auth_userdb *userdbs;
struct sasl_server_request {
pool_t pool;
- struct sasl_server *server;
+ struct sasl_server_instance *sinst;
struct sasl_server_req_ctx *rctx;
struct sasl_server_mech_request *mech;
sasl_server_mech_passdb_callback_t *passdb_callback;
};
+struct sasl_server_instance {
+ struct sasl_server *server;
+ pool_t pool;
+ int refcount;
+ struct sasl_server_instance *prev, *next;
+ struct event *event;
+
+ unsigned int requests;
+};
+
struct sasl_server {
pool_t pool;
struct event *event;
const struct sasl_server_request_funcs *funcs;
+ struct sasl_server_instance *instances;
+
unsigned int requests;
};
*/
void sasl_server_request_create(struct sasl_server_req_ctx *rctx,
- struct sasl_server *server,
+ struct sasl_server_instance *sinst,
const struct sasl_server_mech_def *mech,
const char *protocol,
struct event *event_parent)
{
+ struct sasl_server *server = sinst->server;
struct auth_request *request =
container_of(rctx, struct auth_request, sasl.req);
struct sasl_server_request *req;
pool = request->pool;
req = p_new(pool, struct sasl_server_request, 1);
req->pool = pool;
- req->server = server;
+ req->sinst = sinst;
req->rctx = rctx;
+ sinst->requests++;
server->requests++;
struct sasl_server_mech_request *mreq;
if (req == NULL)
return;
- struct sasl_server *server = req->server;
+ struct sasl_server_instance *sinst = req->sinst;
+ struct sasl_server *server = sinst->server;
struct sasl_server_mech_request *mreq = req->mech;
+ i_assert(sinst->requests > 0);
+ sinst->requests--;
i_assert(server->requests > 0);
server->requests--;
const char *authid)
{
struct sasl_server_request *req = mreq->req;
- struct sasl_server *server = req->server;
+ struct sasl_server *server = req->sinst->server;
const struct sasl_server_request_funcs *funcs = server->funcs;
i_assert(funcs->request_set_authid != NULL);
const char *authzid)
{
struct sasl_server_request *req = mreq->req;
- struct sasl_server *server = req->server;
+ struct sasl_server *server = req->sinst->server;
const struct sasl_server_request_funcs *funcs = server->funcs;
i_assert(funcs->request_set_authzid != NULL);
const char *realm)
{
struct sasl_server_request *req = mreq->req;
- struct sasl_server *server = req->server;
+ struct sasl_server *server = req->sinst->server;
const struct sasl_server_request_funcs *funcs = server->funcs;
i_assert(funcs->request_set_realm != NULL);
const char **field_r)
{
struct sasl_server_request *req = mreq->req;
- struct sasl_server *server = req->server;
+ struct sasl_server *server = req->sinst->server;
const struct sasl_server_request_funcs *funcs = server->funcs;
if (funcs->request_get_extra_field == NULL) {
struct sasl_server_mech_request *mreq, const char *type)
{
struct sasl_server_request *req = mreq->req;
- struct sasl_server *server = req->server;
+ struct sasl_server *server = req->sinst->server;
const struct sasl_server_request_funcs *funcs = server->funcs;
i_assert(funcs->request_start_channel_binding != NULL);
struct sasl_server_mech_request *mreq, buffer_t **data_r)
{
struct sasl_server_request *req = mreq->req;
- struct sasl_server *server = req->server;
+ struct sasl_server *server = req->sinst->server;
const struct sasl_server_request_funcs *funcs = server->funcs;
i_assert(funcs->request_accept_channel_binding != NULL);
const void *data, size_t data_size)
{
struct sasl_server_request *req = mreq->req;
- struct sasl_server *server = req->server;
+ struct sasl_server *server = req->sinst->server;
const struct sasl_server_request_funcs *funcs = server->funcs;
const struct sasl_server_output output = {
const void *data, size_t data_size)
{
struct sasl_server_request *req = mreq->req;
- struct sasl_server *server = req->server;
+ struct sasl_server *server = req->sinst->server;
const struct sasl_server_request_funcs *funcs = server->funcs;
const struct sasl_server_output output = {
const void *data, size_t data_size)
{
struct sasl_server_request *req = mreq->req;
- struct sasl_server *server = req->server;
+ struct sasl_server *server = req->sinst->server;
const struct sasl_server_request_funcs *funcs = server->funcs;
const struct sasl_server_output output = {
sasl_server_mech_passdb_callback_t *callback)
{
struct sasl_server_request *req = mreq->req;
- struct sasl_server *server = req->server;
+ struct sasl_server *server = req->sinst->server;
const struct sasl_server_request_funcs *funcs = server->funcs;
req->passdb_type = SASL_SERVER_PASSDB_TYPE_VERIFY_PLAIN;
sasl_server_mech_passdb_callback_t *callback)
{
struct sasl_server_request *req = mreq->req;
- struct sasl_server *server = req->server;
+ struct sasl_server *server = req->sinst->server;
const struct sasl_server_request_funcs *funcs = server->funcs;
req->passdb_type = SASL_SERVER_PASSDB_TYPE_LOOKUP_CREDENTIALS;
sasl_server_mech_passdb_callback_t *callback)
{
struct sasl_server_request *req = mreq->req;
- struct sasl_server *server = req->server;
+ struct sasl_server *server = req->sinst->server;
const struct sasl_server_request_funcs *funcs = server->funcs;
req->passdb_type = SASL_SERVER_PASSDB_TYPE_SET_CREDENTIALS;
/* Copyright (c) 2023 Dovecot authors, see the included COPYING file */
#include "lib.h"
+#include "llist.h"
#include "sasl-server-private.h"
.name = "sasl-server"
};
+/*
+ * Instance
+ */
+
+struct sasl_server_instance *
+sasl_server_instance_create(struct sasl_server *server,
+ const struct sasl_server_settings *set)
+{
+ struct sasl_server_instance *sinst;
+ pool_t pool;
+
+ pool = pool_alloconly_create(
+ MEMPOOL_GROWING"sasl_server_instance", 2048);
+ sinst = p_new(pool, struct sasl_server_instance, 1);
+ sinst->pool = pool;
+ sinst->refcount = 1;
+ sinst->server = server;
+
+ if (set->event_parent == NULL)
+ sinst->event = event_create(server->event);
+ else {
+ sinst->event = event_create(set->event_parent);
+ event_add_category(sinst->event, &event_category_sasl_server);
+ event_set_append_log_prefix(sinst->event, "sasl: ");
+ }
+
+ DLLIST_PREPEND(&server->instances, sinst);
+
+ return sinst;
+}
+
+void sasl_server_instance_ref(struct sasl_server_instance *sinst)
+{
+ i_assert(sinst->refcount > 0);
+ sinst->refcount++;
+}
+
+void sasl_server_instance_unref(struct sasl_server_instance **_sinst)
+{
+ struct sasl_server_instance *sinst = *_sinst;
+
+ if (sinst == NULL)
+ return;
+ *_sinst = NULL;
+
+ i_assert(sinst->refcount > 0);
+ if (--sinst->refcount > 0)
+ return;
+
+ struct sasl_server *server = sinst->server;
+
+ i_assert(sinst->requests == 0);
+
+ DLLIST_REMOVE(&server->instances, sinst);
+
+ event_unref(&sinst->event);
+ pool_unref(&sinst->pool);
+}
+
/*
* Server
*/
return;
*_server = NULL;
+ i_assert(server->instances == NULL);
i_assert(server->requests == 0);
event_unref(&server->event);
struct sasl_server_mech_def;
struct sasl_server_request;
struct sasl_server_req_ctx;
+struct sasl_server_instance;
struct sasl_server;
enum sasl_passdb_result_status {
} credentials;
};
+struct sasl_server_settings {
+ /* Event to use for the SASL server instance. */
+ struct event *event_parent;
+};
+
/*
* Request
*/
};
void sasl_server_request_create(struct sasl_server_req_ctx *rctx,
- struct sasl_server *server,
+ struct sasl_server_instance *sinst,
const struct sasl_server_mech_def *mech,
const char *protocol,
struct event *event_parent);
void sasl_server_request_input(struct sasl_server_req_ctx *rctx,
const unsigned char *data, size_t data_size);
+/*
+ * Instance
+ */
+
+struct sasl_server_instance *
+sasl_server_instance_create(struct sasl_server *server,
+ const struct sasl_server_settings *set);
+void sasl_server_instance_ref(struct sasl_server_instance *sinst);
+void sasl_server_instance_unref(struct sasl_server_instance **_sinst);
+
/*
* Server
*/