X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/9f6b3bf5187562bac4c96e3ed6a17740d01489fa..a85c067ba6c6940512cf57ec213277a370d87e70:/src/src/auths/gsasl_exim.c diff --git a/src/src/auths/gsasl_exim.c b/src/src/auths/gsasl_exim.c index bae5f081b..aac9c84e6 100644 --- a/src/src/auths/gsasl_exim.c +++ b/src/src/auths/gsasl_exim.c @@ -5,6 +5,7 @@ /* Copyright (c) The Exim Maintainers 2019 - 2022 */ /* Copyright (c) University of Cambridge 1995 - 2018 */ /* See the file NOTICE for conditions of use and distribution. */ +/* SPDX-License-Identifier: GPL-2.0-only */ /* Copyright (c) Twitter Inc 2012 Author: Phil Pennock */ @@ -39,22 +40,34 @@ static void dummy(int x) { dummy2(x-1); } #include "gsasl_exim.h" -#if GSASL_VERSION_MINOR >= 10 -# define EXIM_GSASL_HAVE_SCRAM_SHA_256 -# define EXIM_GSASL_SCRAM_S_KEY +#if GSASL_VERSION_MAJOR == 2 -#elif GSASL_VERSION_MINOR == 9 # define EXIM_GSASL_HAVE_SCRAM_SHA_256 +# define EXIM_GSASL_SCRAM_S_KEY +# if GSASL_VERSION_MINOR >= 1 +# define EXIM_GSASL_HAVE_EXPORTER +# elif GSASL_VERSION_PATCH >= 1 +# define EXIM_GSASL_HAVE_EXPORTER +# endif -# if GSASL_VERSION_PATCH >= 1 +#elif GSASL_VERSION_MAJOR == 1 +# if GSASL_VERSION_MINOR >= 10 +# define EXIM_GSASL_HAVE_SCRAM_SHA_256 # define EXIM_GSASL_SCRAM_S_KEY -# endif -# if GSASL_VERSION_PATCH < 2 + +# elif GSASL_VERSION_MINOR == 9 +# define EXIM_GSASL_HAVE_SCRAM_SHA_256 + +# if GSASL_VERSION_PATCH >= 1 +# define EXIM_GSASL_SCRAM_S_KEY +# endif +# if GSASL_VERSION_PATCH < 2 +# define CHANNELBIND_HACK +# endif + +# else # define CHANNELBIND_HACK # endif - -#else -# define CHANNELBIND_HACK #endif /* Convenience for testing strings */ @@ -258,7 +271,7 @@ if (!cb_state) if (prop == GSASL_CB_TLS_UNIQUE) { uschar * s; - if ((s = gsasl_callback_hook_get(ctx))) + if ((s = gsasl_callback_hook_get(ctx))) /* Gross hack for early lib vers */ { HDEBUG(D_auth) debug_printf("GSASL_CB_TLS_UNIQUE from ctx hook\n"); gsasl_property_set(sctx, GSASL_CB_TLS_UNIQUE, CS s); @@ -332,6 +345,9 @@ switch (prop) #ifdef EXIM_GSASL_SCRAM_S_KEY case GSASL_SCRAM_STOREDKEY: return US"SCRAM_STOREDKEY"; case GSASL_SCRAM_SERVERKEY: return US"SCRAM_SERVERKEY"; +#endif +#ifdef EXIM_GSASL_HAVE_EXPORTER /* v. 2.1.0 */ + case GSASL_CB_TLS_EXPORTER: return US"CB_TLS_EXPORTER"; #endif case GSASL_CB_TLS_UNIQUE: return US"CB_TLS_UNIQUE"; case GSASL_SAML20_IDP_IDENTIFIER: return US"SAML20_IDP_IDENTIFIER"; @@ -351,6 +367,14 @@ switch (prop) return CUS string_sprintf("(unknown prop: %d)", (int)prop); } +static void +preload_prop(Gsasl_session * sctx, Gsasl_property propcode, const uschar * val) +{ +DEBUG(D_auth) debug_printf("preloading prop %s val %s\n", + gsasl_prop_code_to_name(propcode), val); +gsasl_property_set(sctx, propcode, CCS val); +} + /************************************************* * Server entry point * *************************************************/ @@ -358,12 +382,12 @@ return CUS string_sprintf("(unknown prop: %d)", (int)prop); /* For interface, see auths/README */ int -auth_gsasl_server(auth_instance *ablock, uschar *initial_data) +auth_gsasl_server(auth_instance * ablock, uschar * initial_data) { -char *tmps; -char *to_send, *received; -Gsasl_session *sctx = NULL; -auth_gsasl_options_block *ob = +uschar * tmps; +char * to_send, * received; +Gsasl_session * sctx = NULL; +auth_gsasl_options_block * ob = (auth_gsasl_options_block *)(ablock->options_block); struct callback_exim_state cb_state; int rc, auth_result, exim_error, exim_error_override; @@ -406,18 +430,18 @@ cb_state.ablock = ablock; cb_state.currently = CURRENTLY_SERVER; gsasl_session_hook_set(sctx, &cb_state); -tmps = CS expand_string(ob->server_service); -gsasl_property_set(sctx, GSASL_SERVICE, tmps); -tmps = CS expand_string(ob->server_hostname); -gsasl_property_set(sctx, GSASL_HOSTNAME, tmps); +tmps = expand_string(ob->server_service); +preload_prop(sctx, GSASL_SERVICE, tmps); +tmps = expand_string(ob->server_hostname); +preload_prop(sctx, GSASL_HOSTNAME, tmps); if (ob->server_realm) { - tmps = CS expand_string(ob->server_realm); + tmps = expand_string(ob->server_realm); if (tmps && *tmps) - gsasl_property_set(sctx, GSASL_REALM, tmps); + preload_prop(sctx, GSASL_REALM, tmps); } /* We don't support protection layers. */ -gsasl_property_set(sctx, GSASL_QOPS, "qop-auth"); +preload_prop(sctx, GSASL_QOPS, US "qop-auth"); #ifndef DISABLE_TLS if (tls_in.channelbinding) @@ -451,7 +475,12 @@ if (tls_in.channelbinding) HDEBUG(D_auth) debug_printf("Auth %s: Enabling channel-binding\n", ablock->name); # ifndef CHANNELBIND_HACK - gsasl_property_set(sctx, GSASL_CB_TLS_UNIQUE, CCS tls_in.channelbinding); + preload_prop(sctx, +# ifdef EXIM_GSASL_HAVE_EXPORTER + tls_in.channelbind_exporter ? GSASL_CB_TLS_EXPORTER : +# endif + GSASL_CB_TLS_UNIQUE, + tls_in.channelbinding); # endif } else @@ -811,13 +840,13 @@ return TRUE; int auth_gsasl_client( - auth_instance *ablock, /* authenticator block */ + auth_instance * ablock, /* authenticator block */ void * sx, /* connection */ int timeout, /* command timeout */ - uschar *buffer, /* buffer for reading response */ + uschar * buffer, /* buffer for reading response */ int buffsize) /* size of buffer */ { -auth_gsasl_options_block *ob = +auth_gsasl_options_block * ob = (auth_gsasl_options_block *)(ablock->options_block); Gsasl_session * sctx = NULL; struct callback_exim_state cb_state; @@ -883,7 +912,12 @@ if (tls_out.channelbinding) HDEBUG(D_auth) debug_printf("Auth %s: Enabling channel-binding\n", ablock->name); # ifndef CHANNELBIND_HACK - gsasl_property_set(sctx, GSASL_CB_TLS_UNIQUE, CCS tls_out.channelbinding); + preload_prop(sctx, +# ifdef EXIM_GSASL_HAVE_EXPORTER + tls_out.channelbind_exporter ? GSASL_CB_TLS_EXPORTER : +# endif + GSASL_CB_TLS_UNIQUE, + tls_out.channelbinding); # endif } else @@ -968,9 +1002,18 @@ HDEBUG(D_auth) debug_printf("GNU SASL callback %s for %s/%s as client\n", gsasl_prop_code_to_name(prop), ablock->name, ablock->public_name); switch (prop) { - case GSASL_CB_TLS_UNIQUE: /*XXX should never get called for this */ - HDEBUG(D_auth) - debug_printf(" filling in\n"); +#ifdef EXIM_GSASL_HAVE_EXPORTER + case GSASL_CB_TLS_EXPORTER: /* Should never get called for this, as pre-set */ + if (!tls_out.channelbind_exporter) break; + HDEBUG(D_auth) debug_printf(" filling in\n"); + gsasl_property_set(sctx, GSASL_CB_TLS_EXPORTER, CCS tls_out.channelbinding); + return GSASL_OK; +#endif + case GSASL_CB_TLS_UNIQUE: /* Should never get called for this, as pre-set */ +#ifdef EXIM_GSASL_HAVE_EXPORTER + if (tls_out.channelbind_exporter) break; +#endif + HDEBUG(D_auth) debug_printf(" filling in\n"); gsasl_property_set(sctx, GSASL_CB_TLS_UNIQUE, CCS tls_out.channelbinding); return GSASL_OK; case GSASL_SCRAM_SALTED_PASSWORD: