httpd-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From soc-r...@apache.org
Subject svn commit: r367924 - in /httpd/mod_smtpd/trunk/src: mod_smtpd.h smtp_core.c smtp_protocol.c
Date Wed, 11 Jan 2006 04:56:15 GMT
Author: soc-rian
Date: Tue Jan 10 20:55:55 2006
New Revision: 367924

URL: http://svn.apache.org/viewcvs?rev=367924&view=rev
Log:
All commands are now checked for syntax according to RFC 2821 and parameters
to rcpt and mail are now parsed and passed in their respective hooks.

Modified:
    httpd/mod_smtpd/trunk/src/mod_smtpd.h
    httpd/mod_smtpd/trunk/src/smtp_core.c
    httpd/mod_smtpd/trunk/src/smtp_protocol.c

Modified: httpd/mod_smtpd/trunk/src/mod_smtpd.h
URL: http://svn.apache.org/viewcvs/httpd/mod_smtpd/trunk/src/mod_smtpd.h?rev=367924&r1=367923&r2=367924&view=diff
==============================================================================
--- httpd/mod_smtpd/trunk/src/mod_smtpd.h (original)
+++ httpd/mod_smtpd/trunk/src/mod_smtpd.h Tue Jan 10 20:55:55 2006
@@ -98,9 +98,15 @@
     /* string of who this mail is from */
     char *mail_from;
 
+    /* mail-parameters */
+    apr_table_t *mail_parameters;
+
     /* recipient list */
     apr_array_header_t *rcpt_to;
 
+    /* rcpt-parameters */
+    apr_table_t *rcpt_parameters;
+
     /* spooled data file pointer */
     apr_file_t *tfp;
 
@@ -182,10 +188,10 @@
                            char *str));
 APR_DECLARE_EXTERNAL_HOOK(smtpd, SMTPD, smtpd_retcode, mail,
                           (smtpd_conn_rec *scr, smtpd_return_data *in,
-                           char *str));
+                           char *str, apr_table_t *mail_parameters));
 APR_DECLARE_EXTERNAL_HOOK(smtpd, SMTPD, smtpd_retcode, rcpt,
                           (smtpd_conn_rec *scr, smtpd_return_data *in,
-                           char *str));
+                           char *str, apr_table_t *rcpt_parameters));
 APR_DECLARE_EXTERNAL_HOOK(smtpd, SMTPD, smtpd_retcode, vrfy,
                           (smtpd_conn_rec *scr, smtpd_return_data *in,
                            char *str));

Modified: httpd/mod_smtpd/trunk/src/smtp_core.c
URL: http://svn.apache.org/viewcvs/httpd/mod_smtpd/trunk/src/smtp_core.c?rev=367924&r1=367923&r2=367924&view=diff
==============================================================================
--- httpd/mod_smtpd/trunk/src/smtp_core.c (original)
+++ httpd/mod_smtpd/trunk/src/smtp_core.c Tue Jan 10 20:55:55 2006
@@ -33,6 +33,7 @@
 #include "apr_pools.h"
 #include "apr_network_io.h"
 #include "apr_hooks.h"
+#include "apr_tables.h"
 
 #include "mod_smtpd.h"
 #include "smtp.h"
@@ -41,6 +42,9 @@
 module AP_MODULE_DECLARE_DATA smtpd_module;
 ap_filter_rec_t *smtpd_data_input_filter_handle;
 ap_filter_rec_t *smtpd_header_input_filter_handle;
+ap_regex_t *ehlo_compiled_regex;
+ap_regex_t *mail_compiled_regex;
+ap_regex_t *rcpt_compiled_regex;
 
 void smtpd_clear_trans_rec(smtpd_conn_rec *scr)
 {
@@ -54,12 +58,69 @@
     str->mail_from = NULL;
     str->helo = NULL;
     str->headers = apr_table_make(str->p, 5);
+    str->mail_parameters = apr_table_make(str->p, 5);
+    str->rcpt_parameters = apr_table_make(str->p, 5);
     str->input_filters = scr->c->input_filters;
 }
 
 /* private methods */
 /* only used in this file */
 
+static void create_regexes(apr_pool_t *p) {
+    const char *rcpt_syntax = "^[tT][oO]:"
+      "<(("
+      /* [ A-d-l ":"] */
+      "(@([[:alnum:]]([[:alnum:]-]*[[:alnum:]])?)"
+      "(\\.([[:alnum:]]([[:alnum:]-]*[[:alnum:]])?))+"
+      "(,@([[:alnum:]]([[:alnum:]-]*[[:alnum:]])?)"
+      "(\\.([[:alnum:]]([[:alnum:]-]*[[:alnum:]])?))+)*:)?"
+      /* Local-part */
+      "(([-[:alnum:]!#$%&'*+/=?^_`{}|~]+"
+      "(\\.[-[:alnum:]!#$%&'*+/=?^_`{}|~]+)*)|"
+      "(\"(([^\\\"\\\\])|"
+      "(\\\\.))*\"))@"
+      /* Domain */
+      "(([[:alnum:]]([[:alnum:]-]*[[:alnum:]])?)"
+      "(\\.([[:alnum:]]([[:alnum:]-]*[[:alnum:]])?))+))|([pP][oO][sS][mt]"
+      "[aA][sS][tT][eE][rR]))>"
+      /* [Mail-parameters] */
+      "( [[:alnum:]][-[:alnum:]]*(=[^ =]+)?)*$";
+    const char *mail_syntax = "^[fF][rR][oO][mM]:"
+      "<("
+      /* [ A-d-l ":"] */
+      "(@([[:alnum:]]([[:alnum:]-]*[[:alnum:]])?)"
+      "(\\.([[:alnum:]]([[:alnum:]-]*[[:alnum:]])?))+"
+      "(,@([[:alnum:]]([[:alnum:]-]*[[:alnum:]])?)"
+      "(\\.([[:alnum:]]([[:alnum:]-]*[[:alnum:]])?))+)*:)?"
+      /* Local-part */
+      "(([-[:alnum:]!#$%&'*+/=?^_`{}|~]+"
+      "(\\.[-[:alnum:]!#$%&'*+/=?^_`{}|~]+)*)|"
+      "(\"(([^\\\"\\\\])|"
+      "(\\\\.))*\"))@"
+      /* Domain */
+      "(([[:alnum:]]([[:alnum:]-]*[[:alnum:]])?)"
+      "(\\.([[:alnum:]]([[:alnum:]-]*[[:alnum:]])?))+))?>"
+      /* [Mail-parameters] */
+      "( [[:alnum:]][-[:alnum:]]*(=[^ =]+)?)*$";
+    const char *ehlo_syntax = "^((([[:alnum:]]([[:alnum:]-]*[[:alnum:]])?)"
+      "(\\.([[:alnum:]]([[:alnum:]-]*[[:alnum:]])?))+)|"
+      "(\\[\\d{1,3}(\\.\\d{1,3}){3}\\])|"
+      "(\\[IPV6:(([A-Fa-f0-9]{1,4}(:[A-Fa-f0-9]{1,4}){7})|"
+      "(([A-Fa-f0-9]{1,4}(:[A-Fa-f0-9]{1,4}){0,5})?::"
+      "([A-Fa-f0-9]{1,4}(:[A-Fa-f0-9]{1,4}){0,5})?)|"
+      "([A-Fa-f0-9]{1,4}(:[A-Fa-f0-9]{1,4}){5}:\\d{1,3}(\\.\\d{1,3}){3})|"
+      "(([A-Fa-f0-9]{1,4}(:[A-Fa-f0-9]{1,4}){0,3})?::"
+      "([A-Fa-f0-9]{1,4}(:[A-Fa-f0-9]{1,4}){0,3}:)?\\d{1,3}(\\.\\d{1,3}){3})"
+      ")\\])|"
+      "([-[:alnum:]]*[[:alnum:]]:(([^\\[\\]\\\\])|"
+      "(\\\\.))+))"
+      "$";
+
+    ehlo_compiled_regex = ap_pregcomp(p, ehlo_syntax, AP_REG_EXTENDED);
+    mail_compiled_regex = ap_pregcomp(p, mail_syntax, AP_REG_EXTENDED);
+    rcpt_compiled_regex = ap_pregcomp(p, rcpt_syntax, AP_REG_EXTENDED);
+}
+
 /* Creates the main request record for the connection */
 static smtpd_conn_rec *smtpd_create_conn_rec(conn_rec *conn)
 {
@@ -193,6 +254,8 @@
     /* XXX: implement a global (mod_smtpd wise) timeout structure */
     /* modules can register their limit extensions, command help,
        and extensions here */
+    
+    create_regexes(p);
 }
 
 module AP_MODULE_DECLARE_DATA smtpd_module = {
@@ -256,14 +319,16 @@
 /* Implement 'smtpd_run_mail'. */
 APR_IMPLEMENT_EXTERNAL_HOOK_RUN_ALL(smtpd, SMTPD, smtpd_retcode, mail,
                                     (smtpd_conn_rec *scr,
-                                     smtpd_return_data *in, char *str),
-                                    (scr, in, str),
+                                     smtpd_return_data *in, char *str,
+                                     apr_table_t *mail_parameters),
+                                    (scr, in, str, mail_parameters),
                                     SMTPD_OK, SMTPD_DECLINED);
 /* Implement 'smtpd_run_rcpt'. */
 APR_IMPLEMENT_EXTERNAL_HOOK_RUN_ALL(smtpd, SMTPD, smtpd_retcode, rcpt,
                                     (smtpd_conn_rec *scr,
-                                     smtpd_return_data *in, char *str),
-                                    (scr, in, str),
+                                     smtpd_return_data *in, char *str,
+                                     apr_table_t *rcpt_parameters),
+                                    (scr, in, str, rcpt_parameters),
                                     SMTPD_OK, SMTPD_DECLINED);
 /* Implement 'smtpd_run_vrfy'. */
 APR_IMPLEMENT_EXTERNAL_HOOK_RUN_ALL(smtpd, SMTPD, smtpd_retcode, vrfy,

Modified: httpd/mod_smtpd/trunk/src/smtp_protocol.c
URL: http://svn.apache.org/viewcvs/httpd/mod_smtpd/trunk/src/smtp_protocol.c?rev=367924&r1=367923&r2=367924&view=diff
==============================================================================
--- httpd/mod_smtpd/trunk/src/smtp_protocol.c (original)
+++ httpd/mod_smtpd/trunk/src/smtp_protocol.c Tue Jan 10 20:55:55 2006
@@ -29,6 +29,7 @@
 #include "apr_lib.h"
 #include "apr_buckets.h"
 #include "apr_errno.h"
+#include "apr_tables.h"
 #include "scoreboard.h"
 
 #include "apreq2/apreq_parser.h"
@@ -40,6 +41,9 @@
 extern module AP_MODULE_DECLARE_DATA smtpd_module;
 extern ap_filter_rec_t *smtpd_data_input_filter_handle;
 extern ap_filter_rec_t *smtpd_header_input_filter_handle;
+extern ap_regex_t *ehlo_compiled_regex;
+extern ap_regex_t *mail_compiled_regex;
+extern ap_regex_t *rcpt_compiled_regex;
 
 /* these functions are all inlined and static because they
    are only called from one location and only in this file */
@@ -60,7 +64,8 @@
                                      smtpd_return_data *out_data);
 inline static int smtpd_handler_quit(smtpd_conn_rec *scr, char *buffer,
                                      smtpd_return_data *out_data);
-
+inline static int smtpd_handler_vrfy(smtpd_conn_rec *scr, char *buffer,
+                                     smtpd_return_data *out_data);
 
 #define BUFFER_STR_LEN 1024
 void smtpd_process_connection_internal(smtpd_conn_rec *scr)
@@ -115,7 +120,15 @@
     while (smtpd_getline(scr, buffer, BUFFER_STR_LEN, NULL) == APR_SUCCESS) {
         int return_code;
         apr_pool_clear(per_command_pool);
-        command = ap_getword_white_nc(per_command_pool, &buffer);
+        command = buffer;
+
+        
+        buffer = ap_strchr(buffer, ' ');
+        if (buffer != NULL) {
+            *buffer = '\0';
+            buffer++;
+        }
+
         ap_str_tolower(command);
 
         out_data.msgs = NULL;
@@ -142,12 +155,16 @@
             smtpd_respond_oneline(scr, 250, "Ok");
             return_code = 250;
         }
+        else if (ap_strcmp_match("vrfy", command) == 0) {
+            return_code = smtpd_handler_vrfy(scr, buffer, &out_data);
+        }
+      
         else if (ap_strcmp_match("quit", command) == 0) {
             return_code = smtpd_handler_quit(scr, buffer, &out_data);
 
         } else {
             return_code =
-                smtpd_handle_unrecognized_command(scr,&out_data, command,
+                smtpd_handle_unrecognized_command(scr, &out_data, command,
                                                   buffer);
         }
         
@@ -187,11 +204,19 @@
 }
 
 inline static int smtpd_handler_ehlo(smtpd_conn_rec *scr, char *buffer,
-                       smtpd_return_data *out_data)
+                                     smtpd_return_data *out_data)
 {
     smtpd_trans_rec *str = scr->transaction;
-    
-    if (buffer[0] == '\0') {
+    int error;
+
+    if (buffer == NULL) {
+        goto syntax_error;
+    }
+
+    error = ap_regexec(ehlo_compiled_regex, buffer, 0, NULL, 0);
+
+    if (error) {
+    syntax_error:
         smtpd_respond_oneline(scr, 501, "Syntax: EHLO hostname");
         return 501;
     }
@@ -254,9 +279,16 @@
                        smtpd_return_data *out_data)
 {
     smtpd_trans_rec *str = scr->transaction;
-    
-    /* bad syntax */
-    if (buffer[0] == '\0') {
+    int error;
+
+    if (buffer == NULL) {
+        goto syntax_error;
+    }
+
+    error = ap_regexec(ehlo_compiled_regex, buffer, 0, NULL, 0);
+
+    if (error) {
+    syntax_error:
         smtpd_respond_oneline(scr, 501, "Syntax: HELO hostname");
         return 501;
     }
@@ -297,42 +329,84 @@
     return 250;
 }
 
+static void parse_out_parameters(apr_table_t *mail_parameters,
+                                 char *start_parameters) {
+    char *end_para, *end_key;
+
+    while ((start_parameters != '\0')&&
+           (start_parameters != NULL)) {
+        
+        end_para = ap_strchr(start_parameters, ' ');
+        if (end_para != NULL) {
+            end_para[0] = '\0';
+            end_para++;
+        }            
+
+        end_key = ap_strchr(start_parameters, '=');
+        if (end_key == NULL) {
+            apr_table_set(mail_parameters, start_parameters, NULL);
+        } else {
+            end_key[0] = '\0';
+            end_key++;
+            apr_table_set(mail_parameters, start_parameters, end_key);
+        }
+        start_parameters = end_para;
+    }
+}
+
+static int do_callback(void *rec, const char *key, 
+                       const char *value) {
+    smtpd_conn_rec *scr = rec;
+    ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, scr->s,
+                 "stuff: %s %s", key, value);
+    return 1;
+}
+
 inline static int smtpd_handler_mail(smtpd_conn_rec *scr, char *buffer,
                        smtpd_return_data *out_data)
 {
     smtpd_trans_rec *str = scr->transaction;
-    char *loc;
-    
+    char *email_address;
+    char *start_parameters;
+    apr_table_t *mail_parameters;
+    int error;
+
     /* already got mail */
     if (str->trans_state == SMTPD_STATE_GOT_MAIL) {
         smtpd_respond_oneline(scr, 503, "Error: Nested MAIL command");
         return 503;
     }
-    
-    /* bad syntax */
-    if ((loc = ap_strcasestr(buffer, "from:")) == NULL) {
-        smtpd_respond_oneline(scr, 501,  "Syntax: MAIL FROM:<address>");
+
+    if (buffer == NULL) {
+        goto syntax_error;
+    }
+
+    error = ap_regexec(mail_compiled_regex, buffer, 0, NULL, 0);
+
+    if (error) {
+    syntax_error:
+        smtpd_respond_oneline(scr, 501, "Syntax: MAIL FROM:<reverse-path> "
+                              "mail-parameters");
         return 501;
     }
-    
-    loc += sizeof("from:") - 1;
-    
-    ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, scr->s,
-                 "full from_parameter: %s", loc);  
 
-    /* isolate email address in <> */
-    if (loc[0] == '<') {
-        char *end_of_addr;
-        loc++;
-        end_of_addr = strchr(loc, '>');
-        if (end_of_addr) {
-            *end_of_addr = '\0';
-        } else {
-            smtpd_respond_oneline(scr, 501, "Bad sender address syntax");
-        }
+    /* logging will be robustified later 
+       ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, scr->s,
+       "full from_parameter: %s", loc);  
+    */
+
+    mail_parameters = apr_table_make(out_data->p, 5);
+
+    /* parse out reverse-path*/
+    email_address = buffer + sizeof("from:<") - 1;
+    start_parameters = ap_strchr(email_address, '>');
+    start_parameters[0] = '\0';
+
+    if (start_parameters[1] != '\0') {
+        parse_out_parameters(mail_parameters, start_parameters+2);
     }
 
-    switch(smtpd_run_mail(scr, out_data, loc)) {
+    switch(smtpd_run_mail(scr, out_data, email_address, mail_parameters)) {
     case SMTPD_DONE:
         return 1;
     case SMTPD_DONE_DISCONNECT:
@@ -340,7 +414,7 @@
         return 0;
     case SMTPD_DENY:
         ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, scr->s,
-                     "deny mail from %s (%s)", loc,
+                     "deny mail from %s (%s)", email_address,
                      out_data->msgs ? ((char **)out_data->msgs->elts)[0] : "");
 
         if (out_data->msgs) {
             smtpd_respond_multiline(scr, 550, out_data->msgs);
@@ -351,7 +425,7 @@
         return 550;
     case SMTPD_DENYSOFT:
         ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, scr->s,
-                     "denysoft mail from %s (%s)", loc,
+                     "denysoft mail from %s (%s)", email_address,
                      out_data->msgs ? ((char **)out_data->msgs->elts)[0] : "");
 
         if (out_data->msgs) {
             smtpd_respond_multiline(scr, 450, out_data->msgs);
@@ -362,7 +436,7 @@
         return 450;
     case SMTPD_DENY_DISCONNECT:
         ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, scr->s,
-                     "deny mail from %s (%s)", loc,
+                     "deny mail from %s (%s)", email_address,
                      out_data->msgs ? ((char **)out_data->msgs->elts)[0] : "");
 
         if (out_data->msgs) {
             smtpd_respond_multiline(scr, 550, out_data->msgs);
@@ -374,7 +448,7 @@
         return 0;
     case SMTPD_DENYSOFT_DISCONNECT:
         ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, scr->s,
-                     "denysoft mail from %s (%s)", loc,
+                     "denysoft mail from %s (%s)", email_address,
                      out_data->msgs ? ((char **)out_data->msgs->elts)[0] : "");
 
         if (out_data->msgs) {
             smtpd_respond_multiline(scr, 450, out_data->msgs);
@@ -388,8 +462,18 @@
         break;
     }
     
+    apr_table_do(do_callback, scr, mail_parameters, NULL);
+
     /* default handling */
-    str->mail_from = apr_pstrdup(str->p, loc);
+    str->mail_from = apr_pstrdup(str->p, email_address);
+    /* REVIEW: Should we not create the str->mail_parameters at reset time
+       and just create it now with:
+       str->mail_parameters = apr_table_copy(str->p, mail_parameters);
+       or keep how it's done below?
+    */
+    mail_parameters = apr_table_copy(str->p, mail_parameters);
+    apr_table_overlap(str->mail_parameters, mail_parameters,
+                      APR_OVERLAP_TABLES_SET);
     str->trans_state = SMTPD_STATE_GOT_MAIL;
     smtpd_respond_oneline(scr, 250, "Ok");
     
@@ -400,37 +484,43 @@
                        smtpd_return_data *out_data)
 {
     smtpd_trans_rec *str = scr->transaction;
-    char *loc;
-    
+    char *email_address;
+    char *start_parameters;
+    apr_table_t *rcpt_parameters;
+    int error;
+        
     /* need mail first */
     if ((str->trans_state != SMTPD_STATE_GOT_MAIL) &&
         (str->trans_state != SMTPD_STATE_GOT_RCPT)) {
         smtpd_respond_oneline(scr, 503, "Error: need MAIL command");
         return 503;
     }
-    
-    /* bad syntax */
-    if ((loc = ap_strcasestr(buffer, "to:")) == NULL) {
-        smtpd_respond_oneline(scr, 501, "Syntax: RCPT TO:<address>");
+
+    if (buffer == NULL) {
+        goto syntax_error;
+    }
+
+    error = ap_regexec(rcpt_compiled_regex, buffer, 0, NULL, 0);
+
+    if (error) {
+    syntax_error:
+        smtpd_respond_oneline(scr, 501, "Syntax: RCPT TO:<forward-path> "
+                              "rcpt-parameters");
         return 501;
     }
-    
-    loc += sizeof("to:") - 1;
 
-    /* isolate email address in <> */
-    if (loc[0] == '<') {
-        char *end_of_addr;
-        loc++;
-        end_of_addr = strchr(loc, '>');
-        if (end_of_addr) {
-            *end_of_addr = '\0';
-        } else {
-            smtpd_respond_oneline(scr, 501, "Bad recipient address syntax");
-            return 501;
-        }
+    rcpt_parameters = apr_table_make(out_data->p, 5);
+
+    /* parse out reverse-path*/
+    email_address = buffer + sizeof("to:<") - 1;
+    start_parameters = ap_strchr(email_address, '>');
+    start_parameters[0] = '\0';
+
+    if (start_parameters[1] != '\0') {
+        parse_out_parameters(rcpt_parameters, start_parameters+2);
     }
-    
-    switch(smtpd_run_rcpt(scr, out_data, loc)) {
+
+    switch(smtpd_run_rcpt(scr, out_data, email_address, rcpt_parameters)) {
     case SMTPD_DONE:
         return 1;
     case SMTPD_DONE_DISCONNECT:
@@ -482,7 +572,10 @@
     }
     
     /* add a recipient */
-    (*((char **)apr_array_push(str->rcpt_to))) = apr_pstrdup(str->p, loc);
+    rcpt_parameters = apr_table_copy(str->p, rcpt_parameters);
+    apr_table_overlap(str->rcpt_parameters, rcpt_parameters,
+                      APR_OVERLAP_TABLES_SET);
+    (*((char **)apr_array_push(str->rcpt_to))) = apr_pstrdup(str->p, email_address);
     str->trans_state = SMTPD_STATE_GOT_RCPT;
     smtpd_respond_oneline(scr, 250, "Ok");
     
@@ -550,6 +643,11 @@
     apr_bucket_brigade *bb;
     apr_bucket *e;
 
+    if (buffer != NULL) {
+        smtpd_respond_oneline(scr, 501, "Syntax: DATA");
+        return 501;
+    }
+
     switch(smtpd_run_data(scr, out_data)) {
     case SMTPD_DONE:
         return 1;
@@ -715,6 +813,11 @@
 inline static int smtpd_handler_rset(smtpd_conn_rec *scr, char *buffer,
                        smtpd_return_data *out_data)
 {
+    if (buffer != NULL) {
+        smtpd_respond_oneline(scr, 501, "Syntax: RSET");
+        return 501;
+    }
+
     smtpd_reset_transaction(scr);
     smtpd_respond_oneline(scr, 250, "Ok");
     
@@ -724,6 +827,11 @@
 inline static int smtpd_handler_quit(smtpd_conn_rec *scr, char *buffer,
                        smtpd_return_data *out_data)
 {
+    if (buffer != NULL) {
+        smtpd_respond_oneline(scr, 501, "Syntax: QUIT");
+        return 501;
+    }
+
     if (smtpd_run_quit(scr, out_data) != SMTPD_DONE) {
         smtpd_respond_oneline(scr, 221, "Bye");
     }
@@ -734,6 +842,30 @@
 inline static int smtpd_handler_vrfy(smtpd_conn_rec *scr, char *buffer,
                        smtpd_return_data *out_data)
 {
+    const char *vrfy_syntax = "^(([-[:alnum:]!#$%&'*+/=?^_`{}|~]+)|"
+      "(\".*[^\\\\]\"))$";
+    ap_regex_t *compiled;
+    int error;
+
+    if (buffer == NULL) {
+        goto syntax_error;
+    }
+
+    compiled = ap_pregcomp(out_data->p, vrfy_syntax, AP_REG_EXTENDED);
+    if (!compiled) {
+        smtpd_respond_oneline(scr, 421, "Error: Internal");
+        return SMTPD_DONE_DISCONNECT;
+    }
+
+    error = ap_regexec(compiled, buffer, 0, NULL, 0);
+    ap_pregfree(out_data->p, compiled);
+
+    if (error) {
+    syntax_error:
+        smtpd_respond_oneline(scr, 501, "Syntax: VRFY String");
+        return 501;
+    }
+
     switch(smtpd_run_vrfy(scr, out_data, buffer)) {
     case SMTPD_DONE:
         return 1;



Mime
View raw message