* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2009 */
+/* Copyright (c) University of Cambridge 1995 - 2015 */
/* See the file NOTICE for conditions of use and distribution. */
/* This code was originally contributed by Matthew Byng-Maddick */
loops. */
#ifndef AUTH_CYRUS_SASL
-static void dummy(int x) { dummy(x-1); }
+static void dummy(int x);
+static void dummy2(int x) { dummy(x-1); }
+static void dummy(int x) { dummy2(x-1); }
#else
{
auth_cyrus_sasl_options_block *ob =
(auth_cyrus_sasl_options_block *)(ablock->options_block);
-uschar *list, *listptr, *buffer;
+const uschar *list, *listptr, *buffer;
int rc, i;
unsigned int len;
uschar *rs_point, *expanded_hostname;
log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s authenticator: "
"couldn't initialise Cyrus SASL server connection.", ablock->name);
-rc=sasl_listmech(conn, NULL, "", ":", "", (const char **)(&list), &len, &i);
+rc=sasl_listmech(conn, NULL, "", ":", "", (const char **)&list, &len, &i);
if( rc != SASL_OK )
log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s authenticator: "
"couldn't get Cyrus SASL mechanism list.", ablock->name);
sasl_callback_t cbs[]={{SASL_CB_LIST_END, NULL, NULL}};
sasl_conn_t *conn;
char *realm_expanded;
-int rc, firsttime=1, clen, negotiated_ssf;
+int rc, i, firsttime=1, clen, *negotiated_ssf_ptr=NULL, negotiated_ssf;
unsigned int inlen, outlen;
input=data;
if(inlen)
{
- clen=auth_b64decode(input, &clear);
+ clen = b64decode(input, &clear);
if(clen < 0)
{
return BAD64;
return DEFER;
}
-if (tls_cipher)
+if (tls_in.cipher)
{
- rc = sasl_setprop(conn, SASL_SSF_EXTERNAL, &tls_bits);
+ rc = sasl_setprop(conn, SASL_SSF_EXTERNAL, (sasl_ssf_t *) &tls_in.bits);
if (rc != SASL_OK)
{
HDEBUG(D_auth) debug_printf("Cyrus SASL EXTERNAL SSF set %d failed: %s\n",
- tls_bits, sasl_errstring(rc, NULL, NULL));
+ tls_in.bits, sasl_errstring(rc, NULL, NULL));
auth_defer_msg = US"couldn't set Cyrus SASL EXTERNAL SSF";
sasl_done();
return DEFER;
}
else
- HDEBUG(D_auth) debug_printf("Cyrus SASL set EXTERNAL SSF to %d\n", tls_bits);
+ HDEBUG(D_auth) debug_printf("Cyrus SASL set EXTERNAL SSF to %d\n", tls_in.bits);
}
else
HDEBUG(D_auth) debug_printf("Cyrus SASL: no TLS, no EXTERNAL SSF set\n");
+/* So sasl_setprop() documents non-shorted IPv6 addresses which is incredibly
+annoying; looking at cyrus-imapd-2.3.x source, the IP address is constructed
+with their iptostring() function, which just wraps
+getnameinfo(..., NI_NUMERICHOST|NI_NUMERICSERV), which is equivalent to the
+inet_ntop which we wrap in our host_ntoa() function.
+
+So the docs are too strict and we shouldn't worry about :: contractions. */
+
+/* Set properties for remote and local host-ip;port */
+for (i=0; i < 2; ++i)
+ {
+ struct sockaddr_storage ss;
+ int (*query)(int, struct sockaddr *, socklen_t *);
+ int propnum, port;
+ const uschar *label;
+ uschar *address, *address_port;
+ const char *s_err;
+ socklen_t sslen;
+
+ if (i)
+ {
+ query = &getpeername;
+ propnum = SASL_IPREMOTEPORT;
+ label = CUS"peer";
+ }
+ else
+ {
+ query = &getsockname;
+ propnum = SASL_IPLOCALPORT;
+ label = CUS"local";
+ }
+
+ sslen = sizeof(ss);
+ rc = query(fileno(smtp_in), (struct sockaddr *) &ss, &sslen);
+ if (rc < 0)
+ {
+ HDEBUG(D_auth)
+ debug_printf("Failed to get %s address information: %s\n",
+ label, strerror(errno));
+ break;
+ }
+
+ address = host_ntoa(-1, &ss, NULL, &port);
+ address_port = string_sprintf("%s;%d", address, port);
+
+ rc = sasl_setprop(conn, propnum, address_port);
+ if (rc != SASL_OK)
+ {
+ s_err = sasl_errdetail(conn);
+ HDEBUG(D_auth)
+ debug_printf("Failed to set %s SASL property: [%d] %s\n",
+ label, rc, s_err ? s_err : "<unknown reason>");
+ break;
+ }
+ HDEBUG(D_auth) debug_printf("Cyrus SASL set %s hostport to: %s\n",
+ label, address_port);
+ }
+
rc=SASL_CONTINUE;
while(rc==SASL_CONTINUE)
HDEBUG(D_auth) debug=string_copy(input);
if(inlen)
{
- clen=auth_b64decode(input, &clear);
+ clen = b64decode(input, &clear);
if(clen < 0)
{
sasl_dispose(&conn);
debug_printf("Cyrus SASL %s authentication succeeded for %s\n",
ob->server_mech, auth_vars[0]);
- rc = sasl_getprop(conn, SASL_SSF, (const void **)(&negotiated_ssf));
+ rc = sasl_getprop(conn, SASL_SSF, (const void **)(&negotiated_ssf_ptr));
if (rc != SASL_OK)
{
HDEBUG(D_auth)
sasl_done();
return FAIL;
}
+ negotiated_ssf = *negotiated_ssf_ptr;
HDEBUG(D_auth)
debug_printf("Cyrus SASL %s negotiated SSF: %d\n", ob->server_mech, negotiated_ssf);
if (negotiated_ssf > 0)