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