Regex compile cacheing
[exim.git] / src / src / transports / smtp.c
index 145907ca6363729faf8c934789cd080b81858ef0..6eee04d03124ffa77964065129a82f07cc0f50e6 100644 (file)
@@ -275,7 +275,7 @@ struct list
 
 for (struct list * l = list; l < list + nelem(list); l++)
   if (!*l->re)
-    *l->re = regex_must_compile(l->string, FALSE, TRUE);
+    *l->re = regex_must_compile(l->string, MCS_NOFLAGS, TRUE);
 }
 
 
@@ -764,6 +764,28 @@ return TRUE;
 }
 
 
+/* Grab a string differentiating server behind a loadbalancer, for TLS
+resumption when such servers do not share a session-cache */
+
+static void
+ehlo_response_lbserver(smtp_context * sx, smtp_transport_options_block * ob)
+{
+#if !defined(DISABLE_TLS) && !defined(DISABLE_TLS_RESUME)
+const uschar * s;
+uschar * save_item = iterate_item;
+
+if (sx->conn_args.have_lbserver)
+  return;
+iterate_item = sx->buffer;
+s = expand_cstring(ob->host_name_extract);
+iterate_item = save_item;
+sx->conn_args.host_lbserver = s && !*s ? NULL : s;
+sx->conn_args.have_lbserver = TRUE;
+#endif
+}
+
+
+
 /******************************************************************************/
 
 #ifdef EXPERIMENTAL_ESMTP_LIMITS
@@ -833,10 +855,12 @@ ehlo_limits_apply(sx, sx->peer_limit_mail, sx->peer_limit_rcpt,
 static void
 ehlo_cache_limits_apply(smtp_context * sx)
 {
+# ifndef DISABLE_PIPE_CONNECT
 ehlo_limits_apply(sx, sx->ehlo_resp.limit_mail, sx->ehlo_resp.limit_rcpt,
   sx->ehlo_resp.limit_rcptdom);
+# endif
 }
-#endif
+#endif /*EXPERIMENTAL_ESMTP_LIMITS*/
 
 /******************************************************************************/
 
@@ -867,11 +891,11 @@ write_ehlo_cache_entry(smtp_context * sx)
 {
 open_db dbblock, * dbm_file;
 
-#ifdef EXPERIMENTAL_ESMTP_LIMITS
+# ifdef EXPERIMENTAL_ESMTP_LIMITS
 sx->ehlo_resp.limit_mail = sx->peer_limit_mail;
 sx->ehlo_resp.limit_rcpt = sx->peer_limit_rcpt;
 sx->ehlo_resp.limit_rcptdom = sx->peer_limit_rcptdom;
-#endif
+# endif
 
 if ((dbm_file = dbfn_open(US"misc", O_RDWR, &dbblock, TRUE, TRUE)))
   {
@@ -879,7 +903,7 @@ if ((dbm_file = dbfn_open(US"misc", O_RDWR, &dbblock, TRUE, TRUE)))
   dbdata_ehlo_resp er = { .data = sx->ehlo_resp };
 
   HDEBUG(D_transport)
-#ifdef EXPERIMENTAL_ESMTP_LIMITS
+# ifdef EXPERIMENTAL_ESMTP_LIMITS
     if (sx->ehlo_resp.limit_mail || sx->ehlo_resp.limit_rcpt || sx->ehlo_resp.limit_rcptdom)
       debug_printf("writing clr %04x/%04x cry %04x/%04x lim %05d/%05d/%05d\n",
        sx->ehlo_resp.cleartext_features, sx->ehlo_resp.cleartext_auths,
@@ -887,7 +911,7 @@ if ((dbm_file = dbfn_open(US"misc", O_RDWR, &dbblock, TRUE, TRUE)))
        sx->ehlo_resp.limit_mail, sx->ehlo_resp.limit_rcpt,
        sx->ehlo_resp.limit_rcptdom);
     else
-#endif
+# endif
       debug_printf("writing clr %04x/%04x cry %04x/%04x\n",
        sx->ehlo_resp.cleartext_features, sx->ehlo_resp.cleartext_auths,
        sx->ehlo_resp.crypted_features, sx->ehlo_resp.crypted_auths);
@@ -936,7 +960,7 @@ else
   else
     {
     DEBUG(D_transport)
-#ifdef EXPERIMENTAL_ESMTP_LIMITS
+# ifdef EXPERIMENTAL_ESMTP_LIMITS
       if (er->data.limit_mail || er->data.limit_rcpt || er->data.limit_rcptdom)
        debug_printf("EHLO response bits from cache:"
          " cleartext 0x%04x/0x%04x crypted 0x%04x/0x%04x lim %05d/%05d/%05d\n",
@@ -944,16 +968,16 @@ else
          er->data.crypted_features, er->data.crypted_auths,
          er->data.limit_mail, er->data.limit_rcpt, er->data.limit_rcptdom);
       else
-#endif
+# endif
        debug_printf("EHLO response bits from cache:"
          " cleartext 0x%04x/0x%04x crypted 0x%04x/0x%04x\n",
          er->data.cleartext_features, er->data.cleartext_auths,
          er->data.crypted_features, er->data.crypted_auths);
 
     sx->ehlo_resp = er->data;
-#ifdef EXPERIMENTAL_ESMTP_LIMITS
+# ifdef EXPERIMENTAL_ESMTP_LIMITS
     ehlo_cache_limits_apply(sx);
-#endif
+# endif
     dbfn_close(dbm_file);
     return TRUE;
     }
@@ -976,7 +1000,7 @@ uschar authnum;
 unsigned short authbits = 0;
 
 if (!sx->esmtp) return 0;
-if (!regex_AUTH) regex_AUTH = regex_must_compile(AUTHS_REGEX, FALSE, TRUE);
+if (!regex_AUTH) regex_AUTH = regex_must_compile(AUTHS_REGEX, MCS_NOFLAGS, TRUE);
 if (!regex_match_and_setup(regex_AUTH, sx->buffer, 0, -1)) return 0;
 expand_nmax = -1;                                              /* reset */
 names = string_copyn(expand_nstring[1], expand_nlength[1]);
@@ -1040,6 +1064,8 @@ if (pending_BANNER)
     if (tls_out.active.sock >= 0) rc = DEFER;
     goto fail;
     }
+  /*XXX EXPERIMENTAL_ESMTP_LIMITS ? */
+  ehlo_response_lbserver(sx, sx->conn_args.ob);
   }
 
 if (pending_EHLO)
@@ -1068,10 +1094,10 @@ if (pending_EHLO)
        | OPTION_CHUNKING | OPTION_PRDR | OPTION_DSN | OPTION_PIPE | OPTION_SIZE
        | OPTION_UTF8 | OPTION_EARLY_PIPE
        );
-#ifdef EXPERIMENTAL_ESMTP_LIMITS
+# ifdef EXPERIMENTAL_ESMTP_LIMITS
   if (tls_out.active.sock >= 0 || !(peer_offered & OPTION_TLS))
     ehlo_response_limits_read(sx);
-#endif
+# endif
   if (  peer_offered != sx->peer_offered
      || (authbits = study_ehlo_auths(sx)) != *ap)
     {
@@ -1092,7 +1118,7 @@ if (pending_EHLO)
 
     return OK;         /* just carry on */
     }
-#ifdef EXPERIMENTAL_ESMTP_LIMITS
+# ifdef EXPERIMENTAL_ESMTP_LIMITS
     /* If we are handling LIMITS, compare the actual EHLO LIMITS values with the
     cached values and invalidate cache if different.  OK to carry on with
     connect since values are advisory. */
@@ -1116,7 +1142,7 @@ if (pending_EHLO)
       invalidate_ehlo_cache_entry(sx);
       }
     }
-#endif
+# endif
   }
 return OK;
 
@@ -1537,7 +1563,7 @@ f.smtp_authenticated = FALSE;
 client_authenticator = client_authenticated_id = client_authenticated_sender = NULL;
 
 if (!regex_AUTH)
-  regex_AUTH = regex_must_compile(AUTHS_REGEX, FALSE, TRUE);
+  regex_AUTH = regex_must_compile(AUTHS_REGEX, MCS_NOFLAGS, TRUE);
 
 /* Is the server offering AUTH? */
 
@@ -1823,85 +1849,63 @@ pcre2_match_data * md = pcre2_match_data_create(1, pcre_gen_ctx);
 #ifndef DISABLE_TLS
 if (  checks & OPTION_TLS
    && pcre2_match(regex_STARTTLS,
-                 (PCRE2_SPTR)buf, bsize, 0, PCRE_EOPT, md, pcre_mtc_ctx) < 0)
+                 (PCRE2_SPTR)buf, bsize, 0, PCRE_EOPT, md, pcre_gen_mtc_ctx) < 0)
 #endif
   checks &= ~OPTION_TLS;
 
 if (  checks & OPTION_IGNQ
    && pcre2_match(regex_IGNOREQUOTA,
-                 (PCRE2_SPTR)buf, bsize, 0, PCRE_EOPT, md, pcre_mtc_ctx) < 0)
+                 (PCRE2_SPTR)buf, bsize, 0, PCRE_EOPT, md, pcre_gen_mtc_ctx) < 0)
   checks &= ~OPTION_IGNQ;
 
 if (  checks & OPTION_CHUNKING
    && pcre2_match(regex_CHUNKING,
-                 (PCRE2_SPTR)buf, bsize, 0, PCRE_EOPT, md, pcre_mtc_ctx) < 0)
+                 (PCRE2_SPTR)buf, bsize, 0, PCRE_EOPT, md, pcre_gen_mtc_ctx) < 0)
   checks &= ~OPTION_CHUNKING;
 
 #ifndef DISABLE_PRDR
 if (  checks & OPTION_PRDR
    && pcre2_match(regex_PRDR,
-                 (PCRE2_SPTR)buf, bsize, 0, PCRE_EOPT, md, pcre_mtc_ctx) < 0)
+                 (PCRE2_SPTR)buf, bsize, 0, PCRE_EOPT, md, pcre_gen_mtc_ctx) < 0)
 #endif
   checks &= ~OPTION_PRDR;
 
 #ifdef SUPPORT_I18N
 if (  checks & OPTION_UTF8
    && pcre2_match(regex_UTF8,
-                 (PCRE2_SPTR)buf, bsize, 0, PCRE_EOPT, md, pcre_mtc_ctx) < 0)
+                 (PCRE2_SPTR)buf, bsize, 0, PCRE_EOPT, md, pcre_gen_mtc_ctx) < 0)
 #endif
   checks &= ~OPTION_UTF8;
 
 if (  checks & OPTION_DSN
    && pcre2_match(regex_DSN,
-                 (PCRE2_SPTR)buf, bsize, 0, PCRE_EOPT, md, pcre_mtc_ctx) < 0)
+                 (PCRE2_SPTR)buf, bsize, 0, PCRE_EOPT, md, pcre_gen_mtc_ctx) < 0)
   checks &= ~OPTION_DSN;
 
 if (  checks & OPTION_PIPE
    && pcre2_match(regex_PIPELINING,
-                 (PCRE2_SPTR)buf, bsize, 0, PCRE_EOPT, md, pcre_mtc_ctx) < 0)
+                 (PCRE2_SPTR)buf, bsize, 0, PCRE_EOPT, md, pcre_gen_mtc_ctx) < 0)
   checks &= ~OPTION_PIPE;
 
 if (  checks & OPTION_SIZE
    && pcre2_match(regex_SIZE,
-                 (PCRE2_SPTR)buf, bsize, 0, PCRE_EOPT, md, pcre_mtc_ctx) < 0)
+                 (PCRE2_SPTR)buf, bsize, 0, PCRE_EOPT, md, pcre_gen_mtc_ctx) < 0)
   checks &= ~OPTION_SIZE;
 
 #ifndef DISABLE_PIPE_CONNECT
 if (  checks & OPTION_EARLY_PIPE
    && pcre2_match(regex_EARLY_PIPE,
-                 (PCRE2_SPTR)buf, bsize, 0, PCRE_EOPT, md, pcre_mtc_ctx) < 0)
+                 (PCRE2_SPTR)buf, bsize, 0, PCRE_EOPT, md, pcre_gen_mtc_ctx) < 0)
 #endif
   checks &= ~OPTION_EARLY_PIPE;
 
-pcre2_match_data_free(md);
+/* pcre2_match_data_free(md);  gen ctx needs no free */
 /* debug_printf("%s: found     0x%04x\n", __FUNCTION__, checks); */
 return checks;
 }
 
 
 
-/* Grab a string differentiating server behind a loadbalancer, for TLS
-resumption when such servers do not share a session-cache */
-
-static const uschar *
-ehlo_response_lbserver(uschar * buffer, smtp_transport_options_block * ob)
-{
-#if !defined(DISABLE_TLS) && !defined(DISABLE_TLS_RESUME)
-/* want to make this a main-section option */
-const uschar * s;
-uschar * save_item = iterate_item;
-
-iterate_item = buffer;
-s = expand_cstring(ob->host_name_extract);
-iterate_item = save_item;
-return s && !*s ? NULL : s;
-#else
-return NULL;
-#endif
-}
-
-
-
 /* Callback for emitting a BDAT data chunk header.
 
 If given a nonzero size, first flush any buffered SMTP commands
@@ -2544,7 +2548,6 @@ goto SEND_QUIT;
          : 0
          )
 #endif
-/*XXX RESUMP - sx->buffer has the EHLO-resp, but only if not early-pipe and not continued-connection */
        );
 #ifdef EXPERIMENTAL_ESMTP_LIMITS
       if (tls_out.active.sock >= 0 || !(sx->peer_offered & OPTION_TLS))
@@ -2567,7 +2570,7 @@ goto SEND_QUIT;
          }
        }
 #endif
-      sx->conn_args.host_lbserver = ehlo_response_lbserver(sx->buffer, ob);
+      ehlo_response_lbserver(sx, ob);
       }
 
   /* Set tls_offered if the response to EHLO specifies support for STARTTLS. */
@@ -2670,7 +2673,6 @@ if (  smtp_peer_options & OPTION_TLS
       sx->early_pipe_active = FALSE;
       goto PIPE_CONNECT_RETRY;
       }
-    sx->conn_args.host_lbserver = ehlo_response_lbserver(sx->buffer, ob);
     }
 #endif