dovecot-2.2: Added initial libsasl for implementing client side ...
dovecot at dovecot.org
dovecot at dovecot.org
Sun Jun 9 06:03:51 EEST 2013
details: http://hg.dovecot.org/dovecot-2.2/rev/1cbff0a8a849
changeset: 16486:1cbff0a8a849
user: Timo Sirainen <tss at iki.fi>
date: Sun Jun 09 06:02:14 2013 +0300
description:
Added initial libsasl for implementing client side SASL library.
Initially supports PLAIN and LOGIN mechanisms.
diffstat:
configure.ac | 3 +-
src/Makefile.am | 1 +
src/lib-dovecot/Makefile.am | 1 +
src/lib-sasl/Makefile.am | 16 +++++
src/lib-sasl/mech-login.c | 73 +++++++++++++++++++++++++
src/lib-sasl/mech-plain.c | 68 ++++++++++++++++++++++++
src/lib-sasl/sasl-client-private.h | 33 +++++++++++
src/lib-sasl/sasl-client.c | 104 +++++++++++++++++++++++++++++++++++++
src/lib-sasl/sasl-client.h | 38 +++++++++++++
9 files changed, 336 insertions(+), 1 deletions(-)
diffs (truncated from 398 to 300 lines):
diff -r 7e54af474ea4 -r 1cbff0a8a849 configure.ac
--- a/configure.ac Sun Jun 09 03:10:43 2013 +0300
+++ b/configure.ac Sun Jun 09 06:02:14 2013 +0300
@@ -2559,7 +2559,7 @@
LIBDOVECOT_COMPRESS='$(top_builddir)/src/lib-compression/libcompression.la'
LIBDOVECOT_LDA='$(top_builddir)/src/lib-lda/libdovecot-lda.la'
else
- LIBDOVECOT_DEPS='$(top_builddir)/src/lib-master/libmaster.la $(top_builddir)/src/lib-settings/libsettings.la $(top_builddir)/src/lib-http/libhttp.la $(top_builddir)/src/lib-dict/libdict.la $(top_builddir)/src/lib-dns/libdns.la $(top_builddir)/src/lib-fs/libfs.la $(top_builddir)/src/lib-imap/libimap.la $(top_builddir)/src/lib-mail/libmail.la $(top_builddir)/src/lib-auth/libauth.la $(top_builddir)/src/lib-charset/libcharset.la $(top_builddir)/src/lib-ssl-iostream/libssl_iostream.la $(top_builddir)/src/lib-test/libtest.la $(top_builddir)/src/lib/liblib.la'
+ LIBDOVECOT_DEPS='$(top_builddir)/src/lib-master/libmaster.la $(top_builddir)/src/lib-settings/libsettings.la $(top_builddir)/src/lib-http/libhttp.la $(top_builddir)/src/lib-dict/libdict.la $(top_builddir)/src/lib-dns/libdns.la $(top_builddir)/src/lib-fs/libfs.la $(top_builddir)/src/lib-imap/libimap.la $(top_builddir)/src/lib-mail/libmail.la $(top_builddir)/src/lib-sasl/libsasl.la $(top_builddir)/src/lib-auth/libauth.la $(top_builddir)/src/lib-charset/libcharset.la $(top_builddir)/src/lib-ssl-iostream/libssl_iostream.la $(top_builddir)/src/lib-test/libtest.la $(top_builddir)/src/lib/liblib.la'
LIBDOVECOT="$LIBDOVECOT_DEPS \$(LIBICONV) \$(MODULE_LIBS)"
LIBDOVECOT_STORAGE_LAST='$(top_builddir)/src/lib-storage/list/libstorage_list.la $(top_builddir)/src/lib-storage/index/libstorage_index.la $(top_builddir)/src/lib-storage/libstorage.la $(top_builddir)/src/lib-index/libindex.la $(top_builddir)/src/lib-imap-storage/libimap-storage.la'
LIBDOVECOT_STORAGE_FIRST='$(top_builddir)/src/lib-storage/libstorage_service.la $(top_builddir)/src/lib-storage/register/libstorage_register.la'
@@ -2822,6 +2822,7 @@
src/lib-ntlm/Makefile
src/lib-otp/Makefile
src/lib-dovecot/Makefile
+src/lib-sasl/Makefile
src/lib-settings/Makefile
src/lib-ssl-iostream/Makefile
src/lib-test/Makefile
diff -r 7e54af474ea4 -r 1cbff0a8a849 src/Makefile.am
--- a/src/Makefile.am Sun Jun 09 03:10:43 2013 +0300
+++ b/src/Makefile.am Sun Jun 09 06:02:14 2013 +0300
@@ -7,6 +7,7 @@
lib-charset \
lib-dns \
lib-dict \
+ lib-sasl \
lib-ssl-iostream \
lib-http \
lib-fs \
diff -r 7e54af474ea4 -r 1cbff0a8a849 src/lib-dovecot/Makefile.am
--- a/src/lib-dovecot/Makefile.am Sun Jun 09 03:10:43 2013 +0300
+++ b/src/lib-dovecot/Makefile.am Sun Jun 09 06:02:14 2013 +0300
@@ -7,6 +7,7 @@
../lib-dict/libdict.la \
../lib-imap/libimap.la \
../lib-mail/libmail.la \
+ ../lib-sasl/libsasl.la \
../lib-auth/libauth.la \
../lib-dns/libdns.la \
../lib-charset/libcharset.la \
diff -r 7e54af474ea4 -r 1cbff0a8a849 src/lib-sasl/Makefile.am
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-sasl/Makefile.am Sun Jun 09 06:02:14 2013 +0300
@@ -0,0 +1,16 @@
+noinst_LTLIBRARIES = libsasl.la
+
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src/lib
+
+libsasl_la_SOURCES = \
+ mech-login.c \
+ mech-plain.c \
+ sasl-client.c
+
+headers = \
+ sasl-client.h \
+ sasl-client-private.h
+
+pkginc_libdir=$(pkgincludedir)
+pkginc_lib_HEADERS = $(headers)
diff -r 7e54af474ea4 -r 1cbff0a8a849 src/lib-sasl/mech-login.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-sasl/mech-login.c Sun Jun 09 06:02:14 2013 +0300
@@ -0,0 +1,73 @@
+/* Copyright (c) 2013 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "str.h"
+#include "sasl-client-private.h"
+
+enum login_state {
+ STATE_INIT = 0,
+ STATE_USER,
+ STATE_PASS
+};
+
+struct login_sasl_client {
+ struct sasl_client client;
+ enum login_state state;
+};
+
+static int
+mech_login_input(struct sasl_client *_client,
+ const unsigned char *input ATTR_UNUSED,
+ unsigned int input_len ATTR_UNUSED,
+ const char **error_r)
+{
+ struct login_sasl_client *client = (struct login_sasl_client *)_client;
+
+ if (client->state == STATE_PASS) {
+ *error_r = "Server didn't finish authentication";
+ return -1;
+ }
+ client->state++;
+ return 0;
+}
+
+static int
+mech_login_output(struct sasl_client *_client,
+ const unsigned char **output_r, unsigned int *output_len_r,
+ const char **error_r)
+{
+ struct login_sasl_client *client = (struct login_sasl_client *)_client;
+
+ if (_client->set.authid == NULL) {
+ *error_r = "authid not set";
+ return -1;
+ }
+ if (_client->password == NULL) {
+ *error_r = "password not set";
+ return -1;
+ }
+
+ switch (client->state) {
+ case STATE_INIT:
+ *output_r = &uchar_nul;
+ *output_len_r = 0;
+ return 0;
+ case STATE_USER:
+ *output_r = (const unsigned char *)_client->set.authid;
+ *output_len_r = strlen(_client->set.authid);
+ return 0;
+ case STATE_PASS:
+ *output_r = (const unsigned char *)_client->set.password;
+ *output_len_r = strlen(_client->set.password);
+ return 0;
+ }
+ i_unreached();
+}
+
+const struct sasl_client_mech sasl_client_mech_login = {
+ .name = "LOGIN",
+ .struct_size = sizeof(struct login_sasl_client),
+
+ .input = mech_login_input,
+ .output = mech_login_output
+};
diff -r 7e54af474ea4 -r 1cbff0a8a849 src/lib-sasl/mech-plain.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-sasl/mech-plain.c Sun Jun 09 06:02:14 2013 +0300
@@ -0,0 +1,68 @@
+/* Copyright (c) 2013 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "str.h"
+#include "sasl-client-private.h"
+
+struct plain_sasl_client {
+ struct sasl_client client;
+ bool output_sent;
+};
+
+static int
+mech_plain_input(struct sasl_client *_client,
+ const unsigned char *input ATTR_UNUSED, unsigned int input_len,
+ const char **error_r)
+{
+ struct plain_sasl_client *client = (struct plain_sasl_client *)_client;
+
+ if (!client->output_sent) {
+ if (input_len > 0) {
+ *error_r = "Server sent non-empty initial response";
+ return -1;
+ }
+ } else {
+ *error_r = "Server didn't finish authentication";
+ return -1;
+ }
+ return 0;
+}
+
+static int
+mech_plain_output(struct sasl_client *_client,
+ const unsigned char **output_r, unsigned int *output_len_r,
+ const char **error_r)
+{
+ struct plain_sasl_client *client = (struct plain_sasl_client *)_client;
+ string_t *str;
+
+ if (_client->set.authid == NULL) {
+ *error_r = "authid not set";
+ return -1;
+ }
+ if (_client->password == NULL) {
+ *error_r = "password not set";
+ return -1;
+ }
+
+ str = str_new(_client->pool, 64);
+ if (_client->set.authzid != NULL)
+ str_append(str, _client->set.authzid);
+ str_append_c(str, '\0');
+ str_append(str, _client->set.authid);
+ str_append_c(str, '\0');
+ str_append(str, _client->password);
+
+ *output_r = str_data(str);
+ *output_len_r = str_len(str);
+ client->output_sent = TRUE;
+ return 0;
+}
+
+const struct sasl_client_mech sasl_client_mech_plain = {
+ .name = "PLAIN",
+ .struct_size = sizeof(struct plain_sasl_client),
+
+ .input = mech_plain_input,
+ .output = mech_plain_output
+};
diff -r 7e54af474ea4 -r 1cbff0a8a849 src/lib-sasl/sasl-client-private.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-sasl/sasl-client-private.h Sun Jun 09 06:02:14 2013 +0300
@@ -0,0 +1,33 @@
+#ifndef SASL_CLIENT_PRIVATE_H
+#define SASL_CLIENT_PRIVATE_H
+
+#include "sasl-client.h"
+
+struct sasl_client {
+ pool_t pool;
+ struct sasl_client_settings set;
+ char *password;
+ const struct sasl_client_mech *mech;
+};
+
+struct sasl_client_mech {
+ const char *name;
+ size_t struct_size;
+
+ int (*input)(struct sasl_client *client,
+ const unsigned char *input,
+ unsigned int input_len,
+ const char **error_r);
+ int (*output)(struct sasl_client *client,
+ const unsigned char **output_r,
+ unsigned int *output_len_r,
+ const char **error_r);
+ void (*free)(struct sasl_client *client);
+};
+
+extern const struct sasl_client_mech sasl_client_mech_login;
+
+void sasl_client_mech_register(const struct sasl_client_mech *mech);
+void sasl_client_mech_unregister(const struct sasl_client_mech *mech);
+
+#endif
diff -r 7e54af474ea4 -r 1cbff0a8a849 src/lib-sasl/sasl-client.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-sasl/sasl-client.c Sun Jun 09 06:02:14 2013 +0300
@@ -0,0 +1,104 @@
+/* Copyright (c) 2013 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "array.h"
+#include "safe-memset.h"
+#include "sasl-client-private.h"
+
+static ARRAY(const struct sasl_client_mech *) sasl_mechanisms = ARRAY_INIT;
+
+static const struct sasl_client_mech *
+sasl_client_mech_find_idx(const char *name, unsigned int *idx_r)
+{
+ const struct sasl_client_mech *const *mechp;
+
+ array_foreach(&sasl_mechanisms, mechp) {
+ if (strcasecmp((*mechp)->name, name) == 0) {
+ *idx_r = array_foreach_idx(&sasl_mechanisms, mechp);
+ return *mechp;
+ }
+ }
+ return NULL;
+}
+
+const struct sasl_client_mech *sasl_client_mech_find(const char *name)
+{
+ unsigned int idx;
+
+ return sasl_client_mech_find_idx(name, &idx);
+}
+
+const char *sasl_client_mech_get_name(const struct sasl_client_mech *mech)
+{
+ return mech->name;
+}
+
+void sasl_client_mech_register(const struct sasl_client_mech *mech)
+{
+ array_append(&sasl_mechanisms, &mech, 1);
+}
+
+void sasl_client_mech_unregister(const struct sasl_client_mech *mech)
+{
+ unsigned int idx;
+
+ if (sasl_client_mech_find_idx(mech->name, &idx) == NULL)
+ i_panic("SASL mechanism not registered: %s", mech->name);
+ array_delete(&sasl_mechanisms, idx, 1);
+}
More information about the dovecot-cvs
mailing list