Cyrus SASL: set host;port properties on auth driver
authorPhil Pennock <pdp@exim.org>
Sun, 3 Jun 2012 17:18:03 +0000 (13:18 -0400)
committerPhil Pennock <pdp@exim.org>
Sun, 3 Jun 2012 17:18:03 +0000 (13:18 -0400)
doc/doc-txt/ChangeLog
src/src/auths/cyrus_sasl.c

index 3739345af45b888b0c664f0b1d2d97f037bdbbcc..2db67c045b3a8fa3eed5bcdbb0a322431b7963d9 100644 (file)
@@ -18,6 +18,8 @@ PP/04 First step towards DNSSEC, provide $sender_host_dnssec for
 
 PP/05 DSCP support for outbound connections and control modifier for inbound.
 
 
 PP/05 DSCP support for outbound connections and control modifier for inbound.
 
+PP/06 Cyrus SASL: set local and remote IP;port properties for driver.
+
 
 Exim version 4.80
 -----------------
 
 Exim version 4.80
 -----------------
index 9b80f8d83938c1d85e5acb7dfe223b50c1f497d7..7922363ecb80c09bf74ba12cd03f6f4e46e38d60 100644 (file)
@@ -205,7 +205,7 @@ uschar *debug = NULL;   /* Stops compiler complaining */
 sasl_callback_t cbs[]={{SASL_CB_LIST_END, NULL, NULL}};
 sasl_conn_t *conn;
 char *realm_expanded;
 sasl_callback_t cbs[]={{SASL_CB_LIST_END, NULL, NULL}};
 sasl_conn_t *conn;
 char *realm_expanded;
-int rc, firsttime=1, clen, *negotiated_ssf_ptr=NULL, negotiated_ssf;
+int rc, i, firsttime=1, clen, *negotiated_ssf_ptr=NULL, negotiated_ssf;
 unsigned int inlen, outlen;
 
 input=data;
 unsigned int inlen, outlen;
 
 input=data;
@@ -273,6 +273,64 @@ if (tls_cipher)
 else
   HDEBUG(D_auth) debug_printf("Cyrus SASL: no TLS, no EXTERNAL SSF set\n");
 
 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)
 rc=SASL_CONTINUE;
 
 while(rc==SASL_CONTINUE)