Support TTL from SOA for NXDOMAIN & NODATA cache entries for dnslists. Bug 1395
[exim.git] / src / src / verify.c
index 528a668b81be3f1dfda0b1730db424c893f3ecd4..384739b2b3ea46383e3c4849e9c177743f3819b8 100644 (file)
@@ -98,7 +98,7 @@ if (type[0] == 'd' && cache_record->result != ccache_reject)
   {
   if (length == sizeof(dbdata_callout_cache_obs))
     {
   {
   if (length == sizeof(dbdata_callout_cache_obs))
     {
-    dbdata_callout_cache *new = store_get(sizeof(dbdata_callout_cache));
+    dbdata_callout_cache *new = store_get(sizeof(dbdata_callout_cache), FALSE);
     memcpy(new, cache_record, length);
     new->postmaster_stamp = new->random_stamp = new->time_stamp;
     cache_record = new;
     memcpy(new, cache_record, length);
     new->postmaster_stamp = new->random_stamp = new->time_stamp;
     cache_record = new;
@@ -140,7 +140,7 @@ if (options & vopt_callout_no_cache)
   {
   HDEBUG(D_verify) debug_printf("callout cache: disabled by no_cache\n");
   }
   {
   HDEBUG(D_verify) debug_printf("callout cache: disabled by no_cache\n");
   }
-else if (!(dbm_file = dbfn_open(US"callout", O_RDWR, &dbblock, FALSE)))
+else if (!(dbm_file = dbfn_open(US"callout", O_RDWR, &dbblock, FALSE, TRUE)))
   {
   HDEBUG(D_verify) debug_printf("callout cache: not available\n");
   }
   {
   HDEBUG(D_verify) debug_printf("callout cache: not available\n");
   }
@@ -313,7 +313,7 @@ implying some kind of I/O error. We don't want to write the cache in that case.
 Otherwise the value is ccache_accept, ccache_reject, or ccache_reject_mfnull. */
 
 if (dom_rec->result != ccache_unknown)
 Otherwise the value is ccache_accept, ccache_reject, or ccache_reject_mfnull. */
 
 if (dom_rec->result != ccache_unknown)
-  if (!(dbm_file = dbfn_open(US"callout", O_RDWR|O_CREAT, &dbblock, FALSE)))
+  if (!(dbm_file = dbfn_open(US"callout", O_RDWR|O_CREAT, &dbblock, FALSE, TRUE)))
     {
     HDEBUG(D_verify) debug_printf("callout cache: not available\n");
     }
     {
     HDEBUG(D_verify) debug_printf("callout cache: not available\n");
     }
@@ -335,7 +335,7 @@ is disabled. */
 if (done  &&  addr_rec->result != ccache_unknown)
   {
   if (!dbm_file)
 if (done  &&  addr_rec->result != ccache_unknown)
   {
   if (!dbm_file)
-    dbm_file = dbfn_open(US"callout", O_RDWR|O_CREAT, &dbblock, FALSE);
+    dbm_file = dbfn_open(US"callout", O_RDWR|O_CREAT, &dbblock, FALSE, TRUE);
   if (!dbm_file)
     {
     HDEBUG(D_verify) debug_printf("no callout cache available\n");
   if (!dbm_file)
     {
     HDEBUG(D_verify) debug_printf("no callout cache available\n");
@@ -420,7 +420,7 @@ if (addr->transport == cutthrough.addr.transport)
 
        if (done)
          {
 
        if (done)
          {
-         address_item * na = store_get(sizeof(address_item));
+         address_item * na = store_get(sizeof(address_item), FALSE);
          *na = cutthrough.addr;
          cutthrough.addr = *addr;
          cutthrough.addr.host_used = &cutthrough.host;
          *na = cutthrough.addr;
          cutthrough.addr = *addr;
          cutthrough.addr.host_used = &cutthrough.host;
@@ -687,7 +687,7 @@ tls_retry_connection:
     if permitted */
 
     yield = smtp_setup_conn(&sx, FALSE);
     if permitted */
 
     yield = smtp_setup_conn(&sx, FALSE);
-#ifdef SUPPORT_TLS
+#ifndef DISABLE_TLS
     if (  yield == DEFER
        && addr->basic_errno == ERRNO_TLSFAILURE
        && ob->tls_tempfail_tryclear
     if (  yield == DEFER
        && addr->basic_errno == ERRNO_TLSFAILURE
        && ob->tls_tempfail_tryclear
@@ -819,7 +819,7 @@ tls_retry_connection:
            HDEBUG(D_acl|D_v)
              debug_printf_indent("problem after random/rset/mfrom; reopen conn\n");
            random_local_part = NULL;
            HDEBUG(D_acl|D_v)
              debug_printf_indent("problem after random/rset/mfrom; reopen conn\n");
            random_local_part = NULL;
-#ifdef SUPPORT_TLS
+#ifndef DISABLE_TLS
            tls_close(sx.cctx.tls_ctx, TLS_SHUTDOWN_NOWAIT);
 #endif
            HDEBUG(D_transport|D_acl|D_v) debug_printf_indent("  SMTP(close)>>\n");
            tls_close(sx.cctx.tls_ctx, TLS_SHUTDOWN_NOWAIT);
 #endif
            HDEBUG(D_transport|D_acl|D_v) debug_printf_indent("  SMTP(close)>>\n");
@@ -976,8 +976,7 @@ no_conn:
        {
        extern int acl_where;   /* src/acl.c */
        errno = 0;
        {
        extern int acl_where;   /* src/acl.c */
        errno = 0;
-       addr->message = string_sprintf(
-           "response to \"EHLO\" did not include SMTPUTF8");
+       addr->message = US"response to \"EHLO\" did not include SMTPUTF8";
        addr->user_message = acl_where == ACL_WHERE_RCPT
          ? US"533 no support for internationalised mailbox name"
          : US"550 mailbox unavailable";
        addr->user_message = acl_where == ACL_WHERE_RCPT
          ? US"533 no support for internationalised mailbox name"
          : US"550 mailbox unavailable";
@@ -1002,6 +1001,26 @@ no_conn:
          string_sprintf("response to \"%s\" was: %s",
                          big_buffer, string_printing(sx.buffer));
 
          string_sprintf("response to \"%s\" was: %s",
                          big_buffer, string_printing(sx.buffer));
 
+       /* RFC 5321 section 4.2: the text portion of the response may have only
+       HT, SP, Printable US-ASCII.  Deal with awkward chars by cutting the
+       received message off before passing it onward.  Newlines are ok; they
+       just become a multiline response (but wrapped in the error code we
+       produce). */
+
+       for (uschar * s = sx.buffer;
+            *s && s < sx.buffer + sizeof(sx.buffer);
+            s++)
+         {
+         uschar c = *s;
+         if (c != '\t' && c != '\n' && (c < ' ' || c > '~'))
+           {
+           if (s - sx.buffer < sizeof(sx.buffer) - 12)
+             memcpy(s, "(truncated)", 12);
+           else
+             *s = '\0';
+           break;
+           }
+         }
        addr->user_message = options & vopt_is_recipient
          ? string_sprintf("Callout verification failed:\n%s", sx.buffer)
          : string_sprintf("Called:   %s\nSent:     %s\nResponse: %s",
        addr->user_message = options & vopt_is_recipient
          ? string_sprintf("Callout verification failed:\n%s", sx.buffer)
          : string_sprintf("Called:   %s\nSent:     %s\nResponse: %s",
@@ -1089,7 +1108,7 @@ no_conn:
       for (address_item * caddr = &cutthrough.addr, * parent = addr->parent;
           parent;
           caddr = caddr->parent, parent = parent->parent)
       for (address_item * caddr = &cutthrough.addr, * parent = addr->parent;
           parent;
           caddr = caddr->parent, parent = parent->parent)
-        *(caddr->parent = store_get(sizeof(address_item))) = *parent;
+        *(caddr->parent = store_get(sizeof(address_item), FALSE)) = *parent;
 
       ctctx.outblock.buffer = ctbuffer;
       ctctx.outblock.buffersize = sizeof(ctbuffer);
 
       ctctx.outblock.buffer = ctbuffer;
       ctctx.outblock.buffersize = sizeof(ctbuffer);
@@ -1103,16 +1122,13 @@ no_conn:
       if (options & vopt_callout_recipsender)
         cancel_cutthrough_connection(TRUE, US"not usable for cutthrough");
       if (sx.send_quit)
       if (options & vopt_callout_recipsender)
         cancel_cutthrough_connection(TRUE, US"not usable for cutthrough");
       if (sx.send_quit)
-       {
-       (void) smtp_write_command(&sx, SCMD_FLUSH, "QUIT\r\n");
-
-       /* Wait a short time for response, and discard it */
-       smtp_read_response(&sx, sx.buffer, sizeof(sx.buffer), '2', 1);
-       }
+       if (smtp_write_command(&sx, SCMD_FLUSH, "QUIT\r\n") != -1)
+         /* Wait a short time for response, and discard it */
+         smtp_read_response(&sx, sx.buffer, sizeof(sx.buffer), '2', 1);
 
       if (sx.cctx.sock >= 0)
        {
 
       if (sx.cctx.sock >= 0)
        {
-#ifdef SUPPORT_TLS
+#ifndef DISABLE_TLS
        if (sx.cctx.tls_ctx)
          {
          tls_close(sx.cctx.tls_ctx, TLS_SHUTDOWN_NOWAIT);
        if (sx.cctx.tls_ctx)
          {
          tls_close(sx.cctx.tls_ctx, TLS_SHUTDOWN_NOWAIT);
@@ -1176,7 +1192,7 @@ if (!done)
 /* Come here from within the cache-reading code on fast-track exit. */
 
 END_CALLOUT:
 /* Come here from within the cache-reading code on fast-track exit. */
 
 END_CALLOUT:
-tls_modify_variables(&tls_in);
+tls_modify_variables(&tls_in); /* return variables to inbound values */
 return yield;
 }
 
 return yield;
 }
 
@@ -1218,7 +1234,7 @@ if(cutthrough.cctx.sock < 0)
   return TRUE;
 
 if(
   return TRUE;
 
 if(
-#ifdef SUPPORT_TLS
+#ifndef DISABLE_TLS
    cutthrough.is_tls
    ? tls_write(cutthrough.cctx.tls_ctx, ctctx.outblock.buffer, n, FALSE)
    :
    cutthrough.is_tls
    ? tls_write(cutthrough.cctx.tls_ctx, ctctx.outblock.buffer, n, FALSE)
    :
@@ -1419,7 +1435,7 @@ if(fd >= 0)
   /* Wait a short time for response, and discard it */
   cutthrough_response(&tmp_ctx, '2', NULL, 1);
 
   /* Wait a short time for response, and discard it */
   cutthrough_response(&tmp_ctx, '2', NULL, 1);
 
-#ifdef SUPPORT_TLS
+#ifndef DISABLE_TLS
   if (cutthrough.is_tls)
     {
     tls_close(cutthrough.cctx.tls_ctx, TLS_SHUTDOWN_NOWAIT);
   if (cutthrough.is_tls)
     {
     tls_close(cutthrough.cctx.tls_ctx, TLS_SHUTDOWN_NOWAIT);
@@ -1532,6 +1548,8 @@ if (addr != vaddr)
   vaddr->basic_errno = addr->basic_errno;
   vaddr->more_errno = addr->more_errno;
   vaddr->prop.address_data = addr->prop.address_data;
   vaddr->basic_errno = addr->basic_errno;
   vaddr->more_errno = addr->more_errno;
   vaddr->prop.address_data = addr->prop.address_data;
+  vaddr->prop.variables = NULL;
+  tree_dup((tree_node **)&vaddr->prop.variables, addr->prop.variables);
   copyflag(vaddr, addr, af_pass_message);
   }
 return yield;
   copyflag(vaddr, addr, af_pass_message);
   }
 return yield;
@@ -1927,12 +1945,12 @@ while (addr_new)
           }
         else
           {
           }
         else
           {
-#ifdef SUPPORT_TLS
+#ifndef DISABLE_TLS
          deliver_set_expansions(addr);
 #endif
           rc = do_callout(addr, host_list, &tf, callout, callout_overall,
             callout_connect, options, se_mailfrom, pm_mailfrom);
          deliver_set_expansions(addr);
 #endif
           rc = do_callout(addr, host_list, &tf, callout, callout_overall,
             callout_connect, options, se_mailfrom, pm_mailfrom);
-#ifdef SUPPORT_TLS
+#ifndef DISABLE_TLS
          deliver_set_expansions(NULL);
 #endif
           }
          deliver_set_expansions(NULL);
 #endif
           }
@@ -2092,6 +2110,8 @@ while (addr_new)
       of $address_data to be that of the child */
 
       vaddr->prop.address_data = addr->prop.address_data;
       of $address_data to be that of the child */
 
       vaddr->prop.address_data = addr->prop.address_data;
+      vaddr->prop.variables = NULL;
+      tree_dup((tree_node **)&vaddr->prop.variables, addr->prop.variables);
 
       /* If stopped because more than one new address, cannot cutthrough */
 
 
       /* If stopped because more than one new address, cannot cutthrough */
 
@@ -2193,7 +2213,7 @@ the -bv or -bt case). */
 
 out:
 verify_mode = NULL;
 
 out:
 verify_mode = NULL;
-tls_modify_variables(&tls_in);
+tls_modify_variables(&tls_in); /* return variables to inbound values */
 
 return yield;
 }
 
 return yield;
 }
@@ -2349,7 +2369,7 @@ for (header_line * h = header_list; h; h = h->next)
     if ((*s < 33) || (*s > 126))
       {
       *msgptr = string_sprintf("Invalid character in header \"%.*s\" found",
     if ((*s < 33) || (*s > 126))
       {
       *msgptr = string_sprintf("Invalid character in header \"%.*s\" found",
-                            colon - h->text, h->text);
+                            (int)(colon - h->text), h->text);
       return FAIL;
       }
   }
       return FAIL;
       }
   }
@@ -2748,7 +2768,7 @@ for (;;)
   int size = sizeof(buffer) - (p - buffer);
 
   if (size <= 0) goto END_OFF;   /* Buffer filled without seeing \n. */
   int size = sizeof(buffer) - (p - buffer);
 
   if (size <= 0) goto END_OFF;   /* Buffer filled without seeing \n. */
-  count = ip_recv(&ident_conn_ctx, p, size, rfc1413_query_timeout);
+  count = ip_recv(&ident_conn_ctx, p, size, time(NULL) + rfc1413_query_timeout);
   if (count <= 0) goto END_OFF;  /* Read error or EOF */
 
   /* Scan what we just read, to see if we have reached the terminating \r\n. Be
   if (count <= 0) goto END_OFF;  /* Read error or EOF */
 
   /* Scan what we just read, to see if we have reached the terminating \r\n. Be
@@ -3245,7 +3265,7 @@ int
 verify_check_host(uschar **listptr)
 {
 return verify_check_this_host(CUSS listptr, sender_host_cache, NULL,
 verify_check_host(uschar **listptr)
 {
 return verify_check_this_host(CUSS listptr, sender_host_cache, NULL,
-  (sender_host_address == NULL)? US"" : sender_host_address, NULL);
+  sender_host_address ? sender_host_address : US"", NULL);
 }
 
 
 }
 
 
@@ -3351,7 +3371,7 @@ one_check_dnsbl(uschar *domain, uschar *domain_txt, uschar *keydomain,
   uschar *prepend, uschar *iplist, BOOL bitmask, int match_type,
   int defer_return)
 {
   uschar *prepend, uschar *iplist, BOOL bitmask, int match_type,
   int defer_return)
 {
-dns_answer dnsa;
+dns_answer * dnsa = store_get_dns_answer();
 dns_scan dnss;
 tree_node *t;
 dnsbl_cache_block *cb;
 dns_scan dnss;
 tree_node *t;
 dnsbl_cache_block *cb;
@@ -3376,7 +3396,7 @@ if (  (t = tree_search(dnsbl_cache, query))
 /* Previous lookup was cached */
 
   {
 /* Previous lookup was cached */
 
   {
-  HDEBUG(D_dnsbl) debug_printf("using result of previous DNS lookup\n");
+  HDEBUG(D_dnsbl) debug_printf("dnslists: using result of previous lookup\n");
   }
 
 /* If not cached from a previous lookup, we must do a DNS lookup, and
   }
 
 /* If not cached from a previous lookup, we must do a DNS lookup, and
@@ -3384,7 +3404,7 @@ cache the result in permanent memory. */
 
 else
   {
 
 else
   {
-  uint ttl = 3600;
+  uint ttl = 3600;     /* max TTL for positive cache entries */
 
   store_pool = POOL_PERM;
 
 
   store_pool = POOL_PERM;
 
@@ -3395,16 +3415,16 @@ else
 
   else
     {  /* Set up a tree entry to cache the lookup */
 
   else
     {  /* Set up a tree entry to cache the lookup */
-    t = store_get(sizeof(tree_node) + Ustrlen(query));
+    t = store_get(sizeof(tree_node) + Ustrlen(query), is_tainted(query));
     Ustrcpy(t->name, query);
     Ustrcpy(t->name, query);
-    t->data.ptr = cb = store_get(sizeof(dnsbl_cache_block));
+    t->data.ptr = cb = store_get(sizeof(dnsbl_cache_block), FALSE);
     (void)tree_insertnode(&dnsbl_cache, t);
     }
 
   /* Do the DNS lookup . */
 
   HDEBUG(D_dnsbl) debug_printf("new DNS lookup for %s\n", query);
     (void)tree_insertnode(&dnsbl_cache, t);
     }
 
   /* Do the DNS lookup . */
 
   HDEBUG(D_dnsbl) debug_printf("new DNS lookup for %s\n", query);
-  cb->rc = dns_basic_lookup(&dnsa, query, T_A);
+  cb->rc = dns_basic_lookup(dnsa, query, T_A);
   cb->text_set = FALSE;
   cb->text = NULL;
   cb->rhs = NULL;
   cb->text_set = FALSE;
   cb->text = NULL;
   cb->rhs = NULL;
@@ -3419,34 +3439,58 @@ else
   addresses generated in that way as well.
 
   Mark the cache entry with the "now" plus the minimum of the address TTLs,
   addresses generated in that way as well.
 
   Mark the cache entry with the "now" plus the minimum of the address TTLs,
-  or some suitably far-future time if none were found. */
+  or the RFC 2308 negative-cache value from the SOA if none were found. */
 
 
-  if (cb->rc == DNS_SUCCEED)
+  switch (cb->rc)
     {
     {
-    dns_address ** addrp = &(cb->rhs);
-    for (dns_record * rr = dns_next_rr(&dnsa, &dnss, RESET_ANSWERS); rr;
-         rr = dns_next_rr(&dnsa, &dnss, RESET_NEXT))
-      if (rr->type == T_A)
-        {
-        dns_address *da = dns_address_from_rr(&dnsa, rr);
-        if (da)
-          {
-          *addrp = da;
-          while (da->next) da = da->next;
-          addrp = &da->next;
+    case DNS_SUCCEED:
+      {
+      dns_address ** addrp = &cb->rhs;
+      dns_address * da;
+      for (dns_record * rr = dns_next_rr(dnsa, &dnss, RESET_ANSWERS); rr;
+          rr = dns_next_rr(dnsa, &dnss, RESET_NEXT))
+       if (rr->type == T_A && (da = dns_address_from_rr(dnsa, rr)))
+         {
+         *addrp = da;
+         while (da->next) da = da->next;
+         addrp = &da->next;
          if (ttl > rr->ttl) ttl = rr->ttl;
          if (ttl > rr->ttl) ttl = rr->ttl;
-          }
-        }
+         }
+
+      if (cb->rhs)
+       {
+       cb->expiry = time(NULL) + ttl;
+       break;
+       }
+
+      /* If we didn't find any A records, change the return code. This can
+      happen when there is a CNAME record but there are no A records for what
+      it points to. */
 
 
-    /* If we didn't find any A records, change the return code. This can
-    happen when there is a CNAME record but there are no A records for what
-    it points to. */
+      cb->rc = DNS_NODATA;
+      }
+      /*FALLTHROUGH*/
 
 
-    if (!cb->rhs) cb->rc = DNS_NODATA;
+    case DNS_NOMATCH:
+    case DNS_NODATA:
+      {
+      /* Although there already is a neg-cache layer maintained by
+      dns_basic_lookup(), we have a dnslist cache entry allocated and
+      tree-inserted. So we may as well use it. */
+
+      time_t soa_negttl = dns_expire_from_soa(dnsa);
+      cb->expiry = soa_negttl ? soa_negttl : time(NULL) + ttl;
+      break;
+      }
+
+    default:
+      cb->expiry = time(NULL) + ttl;
+      break;
     }
 
     }
 
-  cb->expiry = time(NULL)+ttl;
   store_pool = old_pool;
   store_pool = old_pool;
+  HDEBUG(D_dnsbl) debug_printf("dnslists: wrote cache entry, ttl=%d\n",
+    (int)(cb->expiry - time(NULL)));
   }
 
 /* We now have the result of the DNS lookup, either newly done, or cached
   }
 
 /* We now have the result of the DNS lookup, either newly done, or cached
@@ -3457,7 +3501,7 @@ list (introduced by "&"), or a negative bitmask list (introduced by "!&").*/
 
 if (cb->rc == DNS_SUCCEED)
   {
 
 if (cb->rc == DNS_SUCCEED)
   {
-  dns_address *da = NULL;
+  dns_address * da = NULL;
   uschar *addlist = cb->rhs->address;
 
   /* For A and AAAA records, there may be multiple addresses from multiple
   uschar *addlist = cb->rhs->address;
 
   /* For A and AAAA records, there may be multiple addresses from multiple
@@ -3576,9 +3620,9 @@ if (cb->rc == DNS_SUCCEED)
   if (!cb->text_set)
     {
     cb->text_set = TRUE;
   if (!cb->text_set)
     {
     cb->text_set = TRUE;
-    if (dns_basic_lookup(&dnsa, query, T_TXT) == DNS_SUCCEED)
-      for (dns_record * rr = dns_next_rr(&dnsa, &dnss, RESET_ANSWERS); rr;
-           rr = dns_next_rr(&dnsa, &dnss, RESET_NEXT))
+    if (dns_basic_lookup(dnsa, query, T_TXT) == DNS_SUCCEED)
+      for (dns_record * rr = dns_next_rr(dnsa, &dnss, RESET_ANSWERS); rr;
+           rr = dns_next_rr(dnsa, &dnss, RESET_NEXT))
         if (rr->type == T_TXT)
          {
          int len = (rr->data)[0];
         if (rr->type == T_TXT)
          {
          int len = (rr->data)[0];
@@ -3694,7 +3738,7 @@ dns_init(FALSE, FALSE, FALSE);    /*XXX dnssec? */
 
 /* Loop through all the domains supplied, until something matches */
 
 
 /* Loop through all the domains supplied, until something matches */
 
-while ((domain = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL)
+while ((domain = string_nextinlist(&list, &sep, buffer, sizeof(buffer))))
   {
   int rc;
   BOOL bitmask = FALSE;
   {
   int rc;
   BOOL bitmask = FALSE;
@@ -3704,7 +3748,7 @@ while ((domain = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL
   uschar *iplist;
   uschar *key;
 
   uschar *iplist;
   uschar *key;
 
-  HDEBUG(D_dnsbl) debug_printf("DNS list check: %s\n", domain);
+  HDEBUG(D_dnsbl) debug_printf("dnslists check: %s\n", domain);
 
   /* Deal with special values that change the behaviour on defer */
 
 
   /* Deal with special values that change the behaviour on defer */
 
@@ -3758,8 +3802,7 @@ while ((domain = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL
   set domain_txt == domain. */
 
   domain_txt = domain;
   set domain_txt == domain. */
 
   domain_txt = domain;
-  comma = Ustrchr(domain, ',');
-  if (comma != NULL)
+  if ((comma = Ustrchr(domain, ',')))
     {
     *comma++ = 0;
     domain = comma;
     {
     *comma++ = 0;
     domain = comma;
@@ -3801,7 +3844,7 @@ while ((domain = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL
          acl_wherenames[where]);
       return ERROR;
       }
          acl_wherenames[where]);
       return ERROR;
       }
-    if (sender_host_address == NULL) return FAIL;    /* can never match */
+    if (!sender_host_address) return FAIL;    /* can never match */
     if (revadd[0] == 0) invert_address(revadd, sender_host_address);
     rc = one_check_dnsbl(domain, domain_txt, sender_host_address, revadd,
       iplist, bitmask, match_type, defer_return);
     if (revadd[0] == 0) invert_address(revadd, sender_host_address);
     rc = one_check_dnsbl(domain, domain_txt, sender_host_address, revadd,
       iplist, bitmask, match_type, defer_return);
@@ -3823,11 +3866,9 @@ while ((domain = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL
     int keysep = 0;
     BOOL defer = FALSE;
     uschar *keydomain;
     int keysep = 0;
     BOOL defer = FALSE;
     uschar *keydomain;
-    uschar keybuffer[256];
     uschar keyrevadd[128];
 
     uschar keyrevadd[128];
 
-    while ((keydomain = string_nextinlist(CUSS &key, &keysep, keybuffer,
-            sizeof(keybuffer))) != NULL)
+    while ((keydomain = string_nextinlist(CUSS &key, &keysep, NULL, 0)))
       {
       uschar *prepend = keydomain;
 
       {
       uschar *prepend = keydomain;
 
@@ -3839,7 +3880,6 @@ while ((domain = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL
 
       rc = one_check_dnsbl(domain, domain_txt, keydomain, prepend, iplist,
         bitmask, match_type, defer_return);
 
       rc = one_check_dnsbl(domain, domain_txt, keydomain, prepend, iplist,
         bitmask, match_type, defer_return);
-
       if (rc == OK)
         {
         dnslist_domain = string_copy(domain_txt);
       if (rc == OK)
         {
         dnslist_domain = string_copy(domain_txt);