summaryrefslogtreecommitdiffstats
path: root/src/lib-sasl/dsasl-client.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib-sasl/dsasl-client.c')
-rw-r--r--src/lib-sasl/dsasl-client.c152
1 files changed, 152 insertions, 0 deletions
diff --git a/src/lib-sasl/dsasl-client.c b/src/lib-sasl/dsasl-client.c
new file mode 100644
index 0000000..bf11d5c
--- /dev/null
+++ b/src/lib-sasl/dsasl-client.c
@@ -0,0 +1,152 @@
+/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "array.h"
+#include "safe-memset.h"
+#include "dsasl-client-private.h"
+
+static int init_refcount = 0;
+static ARRAY(const struct dsasl_client_mech *) dsasl_mechanisms = ARRAY_INIT;
+
+static const struct dsasl_client_mech *
+dsasl_client_mech_find_idx(const char *name, unsigned int *idx_r)
+{
+ const struct dsasl_client_mech *const *mechp;
+
+ array_foreach(&dsasl_mechanisms, mechp) {
+ if (strcasecmp((*mechp)->name, name) == 0) {
+ *idx_r = array_foreach_idx(&dsasl_mechanisms, mechp);
+ return *mechp;
+ }
+ }
+ return NULL;
+}
+
+const struct dsasl_client_mech *dsasl_client_mech_find(const char *name)
+{
+ unsigned int idx;
+
+ return dsasl_client_mech_find_idx(name, &idx);
+}
+
+const char *dsasl_client_mech_get_name(const struct dsasl_client_mech *mech)
+{
+ return mech->name;
+}
+
+void dsasl_client_mech_register(const struct dsasl_client_mech *mech)
+{
+ unsigned int idx;
+
+ if (dsasl_client_mech_find_idx(mech->name, &idx) != NULL) {
+ /* allow plugins to override the default mechanisms */
+ array_delete(&dsasl_mechanisms, idx, 1);
+ }
+ array_push_back(&dsasl_mechanisms, &mech);
+}
+
+void dsasl_client_mech_unregister(const struct dsasl_client_mech *mech)
+{
+ unsigned int idx;
+
+ if (dsasl_client_mech_find_idx(mech->name, &idx) == NULL)
+ i_panic("SASL mechanism not registered: %s", mech->name);
+ array_delete(&dsasl_mechanisms, idx, 1);
+}
+
+struct dsasl_client *dsasl_client_new(const struct dsasl_client_mech *mech,
+ const struct dsasl_client_settings *set)
+{
+ struct dsasl_client *client;
+ pool_t pool = pool_alloconly_create("sasl client", 512);
+
+ client = p_malloc(pool, mech->struct_size);
+ client->pool = pool;
+ client->mech = mech;
+ client->set.authid = p_strdup(pool, set->authid);
+ client->set.authzid = p_strdup(pool, set->authzid);
+ client->password = p_strdup(pool, set->password);
+ client->set.password = client->password;
+ return client;
+}
+
+void dsasl_client_free(struct dsasl_client **_client)
+{
+ struct dsasl_client *client = *_client;
+
+ if (client == NULL)
+ return;
+ *_client = NULL;
+
+ if (client->mech->free != NULL)
+ client->mech->free(client);
+ if (client->password != NULL)
+ safe_memset(client->password, 0, strlen(client->password));
+ pool_unref(&client->pool);
+}
+
+int dsasl_client_input(struct dsasl_client *client,
+ const unsigned char *input, size_t input_len,
+ const char **error_r)
+{
+ if ((client->mech->flags & DSASL_MECH_SEC_ALLOW_NULS) == 0 &&
+ memchr(input, '\0', input_len) != NULL) {
+ *error_r = "Unexpected NUL in input data";
+ return -1;
+ }
+ return client->mech->input(client, input, input_len, error_r);
+}
+
+int dsasl_client_output(struct dsasl_client *client,
+ const unsigned char **output_r, size_t *output_len_r,
+ const char **error_r)
+{
+ return client->mech->output(client, output_r, output_len_r, error_r);
+}
+
+int dsasl_client_set_parameter(struct dsasl_client *client,
+ const char *param, const char *value,
+ const char **error_r)
+{
+ if (client->mech->set_parameter != NULL) {
+ int ret = client->mech->set_parameter(client, param,
+ value, error_r);
+ i_assert(ret >= 0 || *error_r != NULL);
+ return ret;
+ } else
+ return 0;
+}
+
+int dsasl_client_get_result(struct dsasl_client *client,
+ const char *key, const char **value_r,
+ const char **error_r)
+{
+ if (client->mech->get_result != NULL) {
+ int ret =
+ client->mech->get_result(client, key, value_r, error_r);
+ i_assert(ret <= 0 || *value_r != NULL);
+ i_assert(ret >= 0 || *error_r != NULL);
+ return ret;
+ } else
+ return 0;
+}
+
+void dsasl_clients_init(void)
+{
+ if (init_refcount++ > 0)
+ return;
+
+ i_array_init(&dsasl_mechanisms, 8);
+ dsasl_client_mech_register(&dsasl_client_mech_external);
+ dsasl_client_mech_register(&dsasl_client_mech_plain);
+ dsasl_client_mech_register(&dsasl_client_mech_login);
+ dsasl_client_mech_register(&dsasl_client_mech_oauthbearer);
+ dsasl_client_mech_register(&dsasl_client_mech_xoauth2);
+}
+
+void dsasl_clients_deinit(void)
+{
+ if (--init_refcount > 0)
+ return;
+ array_free(&dsasl_mechanisms);
+}