From: Stephan Bosch Date: Wed, 11 Nov 2020 23:09:26 +0000 (+0100) Subject: lib-sasl: Add support for SCRAM-SHA-1 and SCRAM-SHA-256. X-Git-Tag: 2.4.0~3121 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=54d9bf1d99a1449131bc91a471bfb05fa4d22454;p=thirdparty%2Fdovecot%2Fcore.git lib-sasl: Add support for SCRAM-SHA-1 and SCRAM-SHA-256. --- diff --git a/src/lib-imap-client/Makefile.am b/src/lib-imap-client/Makefile.am index 8fe8a8d091..fdc63a0788 100644 --- a/src/lib-imap-client/Makefile.am +++ b/src/lib-imap-client/Makefile.am @@ -36,6 +36,7 @@ test_deps = \ ../lib-mail/libmail.la \ ../lib-charset/libcharset.la \ ../lib-dns/libdns.la \ + ../lib-auth/libauth.la \ ../lib-test/libtest.la \ ../lib/liblib.la diff --git a/src/lib-sasl/Makefile.am b/src/lib-sasl/Makefile.am index c1d916fdc9..ac0e99bb1c 100644 --- a/src/lib-sasl/Makefile.am +++ b/src/lib-sasl/Makefile.am @@ -2,14 +2,18 @@ noinst_LTLIBRARIES = libsasl.la AM_CPPFLAGS = \ -I$(top_srcdir)/src/lib \ - -I$(top_srcdir)/src/lib-test + -I$(top_srcdir)/src/lib-test \ + -I$(top_srcdir)/src/lib-auth libsasl_la_SOURCES = \ mech-external.c \ mech-login.c \ mech-plain.c \ mech-oauthbearer.c \ + mech-scram.c \ dsasl-client.c +libsasl_la_DEPENDENCIES = \ + ../lib-auth/libauth.la headers = \ dsasl-client.h \ @@ -25,6 +29,7 @@ noinst_PROGRAMS = $(test_programs) test_libs = \ $(noinst_LTLIBRARIES) \ + ../lib-auth/libauth.la \ ../lib-test/libtest.la \ ../lib/liblib.la diff --git a/src/lib-sasl/dsasl-client-private.h b/src/lib-sasl/dsasl-client-private.h index 65b86f70b8..00272e9cf7 100644 --- a/src/lib-sasl/dsasl-client-private.h +++ b/src/lib-sasl/dsasl-client-private.h @@ -38,6 +38,8 @@ extern const struct dsasl_client_mech dsasl_client_mech_external; extern const struct dsasl_client_mech dsasl_client_mech_login; extern const struct dsasl_client_mech dsasl_client_mech_oauthbearer; extern const struct dsasl_client_mech dsasl_client_mech_xoauth2; +extern const struct dsasl_client_mech dsasl_client_mech_scram_sha_1; +extern const struct dsasl_client_mech dsasl_client_mech_scram_sha_256; void dsasl_client_mech_register(const struct dsasl_client_mech *mech); void dsasl_client_mech_unregister(const struct dsasl_client_mech *mech); diff --git a/src/lib-sasl/dsasl-client.c b/src/lib-sasl/dsasl-client.c index bf11d5ccd5..aa14809eef 100644 --- a/src/lib-sasl/dsasl-client.c +++ b/src/lib-sasl/dsasl-client.c @@ -142,6 +142,8 @@ void dsasl_clients_init(void) dsasl_client_mech_register(&dsasl_client_mech_login); dsasl_client_mech_register(&dsasl_client_mech_oauthbearer); dsasl_client_mech_register(&dsasl_client_mech_xoauth2); + dsasl_client_mech_register(&dsasl_client_mech_scram_sha_1); + dsasl_client_mech_register(&dsasl_client_mech_scram_sha_256); } void dsasl_clients_deinit(void) diff --git a/src/lib-sasl/mech-scram.c b/src/lib-sasl/mech-scram.c new file mode 100644 index 0000000000..415035d7a3 --- /dev/null +++ b/src/lib-sasl/mech-scram.c @@ -0,0 +1,99 @@ +/* Copyright (c) 2020 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "sha1.h" +#include "sha2.h" +#include "auth-scram-client.h" +#include "dsasl-client-private.h" + +struct scram_dsasl_client { + struct dsasl_client client; + + struct auth_scram_client scram_client; +}; + +static void mech_scram_init(struct scram_dsasl_client *sclient) +{ + struct dsasl_client *client = &sclient->client; + const struct hash_method *hmethod; + + /* SCRAM-SHA-1 */ + if (client->mech == &dsasl_client_mech_scram_sha_1) { + hmethod = &hash_method_sha1; + /* SCRAM-SHA-256 */ + } else if (client->mech == &dsasl_client_mech_scram_sha_256) { + hmethod = &hash_method_sha256; + } else { + i_unreached(); + } + + auth_scram_client_init(&sclient->scram_client, client->pool, hmethod, + client->set.authid, client->set.authzid, + client->password); +} + +static int +mech_scram_input(struct dsasl_client *client, + const unsigned char *input, size_t input_len, + const char **error_r) +{ + struct scram_dsasl_client *sclient = + container_of(client, struct scram_dsasl_client, client); + + if (sclient->scram_client.state == AUTH_SCRAM_CLIENT_STATE_INIT) + mech_scram_init(sclient); + + return auth_scram_client_input(&sclient->scram_client, + input, input_len, error_r); +} + +static int +mech_scram_output(struct dsasl_client *client, + const unsigned char **output_r, size_t *output_len_r, + const char **error_r) +{ + struct scram_dsasl_client *sclient = + container_of(client, struct scram_dsasl_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; + } + + if (sclient->scram_client.state == AUTH_SCRAM_CLIENT_STATE_INIT) + mech_scram_init(sclient); + + auth_scram_client_output(&sclient->scram_client, + output_r, output_len_r); + return 0; +} + +static void mech_scram_free(struct dsasl_client *client) +{ + struct scram_dsasl_client *sclient = + container_of(client, struct scram_dsasl_client, client); + + auth_scram_client_deinit(&sclient->scram_client); +} + +const struct dsasl_client_mech dsasl_client_mech_scram_sha_1 = { + .name = "SCRAM-SHA-1", + .struct_size = sizeof(struct scram_dsasl_client), + + .input = mech_scram_input, + .output = mech_scram_output, + .free = mech_scram_free, +}; + +const struct dsasl_client_mech dsasl_client_mech_scram_sha_256 = { + .name = "SCRAM-SHA-256", + .struct_size = sizeof(struct scram_dsasl_client), + + .input = mech_scram_input, + .output = mech_scram_output, + .free = mech_scram_free, +}; diff --git a/src/lib-smtp/Makefile.am b/src/lib-smtp/Makefile.am index 3763c6f94b..f4ebef0cc6 100644 --- a/src/lib-smtp/Makefile.am +++ b/src/lib-smtp/Makefile.am @@ -111,6 +111,7 @@ test_libs = \ ../lib-ssl-iostream/libssl_iostream.la \ ../lib-settings/libsettings.la \ ../lib-sasl/libsasl.la \ + ../lib-auth/libauth.la \ ../lib-test/libtest.la \ ../lib/liblib.la \ $(MODULE_LIBS) @@ -126,6 +127,7 @@ test_deps = \ ../lib-ssl-iostream/libssl_iostream.la \ ../lib-settings/libsettings.la \ ../lib-sasl/libsasl.la \ + ../lib-auth/libauth.la \ ../lib-test/libtest.la \ ../lib/liblib.la