Hi tech@,

Below is a diff to teach smtpd how to rewrite the sender of
outgoing messages *at the SMTP level* (no From: rewrite).

        # all outoging mails originate from b...@example.com
        accept for all relay as "b...@example.com"

        # local domain is preserved, user is rewritten
        accept for all relay as "bleh"

        # local user is preserved, domain is rewritten
        accept for all relay as "@example.com"

Again, this takes place at the SMTP level, it does not allow
the rewriting of messages and headers, but makes it possible
for smtpd to fake the domain advertised with MAIL FROM and
stop being rejected by strict hosts. 

As a side change, I did a minor change so that:
        accept for local deliver to mbox user "vdom"

becomes:
        accept for local deliver to mbox as "vdom"

Please report regressions ;)


Index: lka_session.c
===================================================================
RCS file: /cvs/src/usr.sbin/smtpd/lka_session.c,v
retrieving revision 1.6
diff -u -p -r1.6 lka_session.c
--- lka_session.c       21 May 2011 18:11:40 -0000      1.6
+++ lka_session.c       25 May 2011 21:46:50 -0000
@@ -392,6 +392,10 @@ lka_session_deliver(struct lka_session *
                        break;
                }
        }
+       else if (new_ep->delivery.type == D_MTA) {
+               if (ep->rule.r_as)
+                       new_ep->delivery.from = *ep->rule.r_as;
+       }
        TAILQ_INSERT_TAIL(&lks->deliverylist, new_ep, entry);
 }
 
Index: parse.y
===================================================================
RCS file: /cvs/src/usr.sbin/smtpd/parse.y,v
retrieving revision 1.75
diff -u -p -r1.75 parse.y
--- parse.y     22 May 2011 21:03:14 -0000      1.75
+++ parse.y     25 May 2011 21:46:51 -0000
@@ -111,18 +111,19 @@ typedef struct {
                struct cond     *cond;
                char            *string;
                struct host     *host;
+               struct mailaddr *maddr;
        } v;
        int lineno;
 } YYSTYPE;
 
 %}
 
-%token QUEUE INTERVAL SIZE LISTEN ON ALL PORT EXPIRE
+%token AS QUEUE INTERVAL SIZE LISTEN ON ALL PORT EXPIRE
 %token MAP TYPE HASH LIST SINGLE SSL SMTPS CERTIFICATE
 %token DNS DB PLAIN EXTERNAL DOMAIN CONFIG SOURCE
 %token  RELAY VIA DELIVER TO MAILDIR MBOX HOSTNAME
 %token ACCEPT REJECT INCLUDE NETWORK ERROR MDA FROM FOR
-%token ARROW ENABLE AUTH TLS LOCAL VIRTUAL USER TAG ALIAS
+%token ARROW ENABLE AUTH TLS LOCAL VIRTUAL TAG ALIAS
 %token <v.string>      STRING
 %token  <v.number>     NUMBER
 %type  <v.map>         map
@@ -130,6 +131,7 @@ typedef struct {
 %type  <v.cond>        condition
 %type  <v.tv>          interval
 %type  <v.object>      mapref
+%type  <v.maddr>       relay_as
 %type  <v.string>      certname user tag on alias
 
 %%
@@ -845,7 +847,7 @@ conditions  : condition                             {
                | '{' condition_list '}'
                ;
 
-user           : USER STRING           {
+user           : AS STRING             {
                        struct passwd *pw;
 
                        pw = getpwnam($2);
@@ -859,6 +861,76 @@ user               : USER STRING           {
                | /* empty */           { $$ = NULL; }
                ;
 
+relay_as       : AS STRING             {
+                       struct mailaddr maddr, *maddrp;
+                       char *p;
+
+                       bzero(&maddr, sizeof (maddr));
+
+                       p = strrchr($2, '@');
+                       if (p == NULL) {
+                               if (strlcpy(maddr.user, $2, sizeof (maddr.user))
+                                   >= sizeof (maddr.user))
+                                       yyerror("user-part too long");
+                                       free($2);
+                                       YYERROR;
+                       }
+                       else {
+                               if (p == $2) {
+                                       /* domain only */
+                                       p++;
+                                       if (strlcpy(maddr.domain, p, sizeof 
(maddr.domain))
+                                           >= sizeof (maddr.domain)) {
+                                               yyerror("user-part too long");
+                                               free($2);
+                                               YYERROR;
+                                       }
+                               }
+                               else {
+                                       *p++ = '\0';
+                                       if (strlcpy(maddr.user, $2, sizeof 
(maddr.user))
+                                           >= sizeof (maddr.user)) {
+                                               yyerror("user-part too long");
+                                               free($2);
+                                               YYERROR;
+                                       }
+                                       if (strlcpy(maddr.domain, p, sizeof 
(maddr.domain))
+                                           >= sizeof (maddr.domain)) {
+                                               yyerror("domain-part too long");
+                                               free($2);
+                                               YYERROR;
+                                       }
+                               }
+                       }
+
+                       if (maddr.user[0] == '\0' && maddr.domain[0] == '\0') {
+                               yyerror("invalid 'relay as' value");
+                               free($2);
+                               YYERROR;
+                       }
+
+                       if (maddr.domain[0] == '\0') {
+                               if (strlcpy(maddr.domain, conf->sc_hostname,
+                                       sizeof (maddr.domain))
+                                   >= sizeof (maddr.domain)) {
+                                       fatalx("domain too long");
+                                       yyerror("domain-part too long");
+                                       free($2);
+                                       YYERROR;
+                               }
+                       }
+                       
+                       maddrp = calloc(1, sizeof (*maddrp));
+                       if (maddrp == NULL)
+                               fatal("calloc");
+                       *maddrp = maddr;
+                       free($2);
+
+                       $$ = maddrp;
+               }
+               | /* empty */           { $$ = NULL; }
+               ;
+
 action         : DELIVER TO MAILDIR user               {
                        rule->r_user = $4;
                        rule->r_action = A_MAILDIR;
@@ -892,11 +964,13 @@ action            : DELIVER TO MAILDIR user               
{
                                fatal("command too long");
                        free($4);
                }
-               | RELAY                         {
+               | RELAY relay_as                        {
                        rule->r_action = A_RELAY;
+                       rule->r_as = $2;
                }
-               | RELAY VIA STRING port ssl certname credentials {
+               | RELAY VIA STRING port ssl certname credentials relay_as {
                        rule->r_action = A_RELAYVIA;
+                       rule->r_as = $8;
 
                        if ($5 == 0 && ($6 != NULL || $7)) {
                                yyerror("error: must specify tls, smtps, or 
ssl");
@@ -1110,6 +1184,7 @@ lookup(char *s)
                { "accept",             ACCEPT },
                { "alias",              ALIAS },
                { "all",                ALL },
+               { "as",                 AS },
                { "auth",               AUTH },
                { "certificate",        CERTIFICATE },
                { "config",             CONFIG },
@@ -1149,7 +1224,6 @@ lookup(char *s)
                { "tls",                TLS },
                { "to",                 TO },
                { "type",               TYPE },
-               { "user",               USER },
                { "via",                VIA },
                { "virtual",            VIRTUAL },
        };
Index: smtpd.h
===================================================================
RCS file: /cvs/src/usr.sbin/smtpd/smtpd.h,v
retrieving revision 1.226
diff -u -p -r1.226 smtpd.h
--- smtpd.h     21 May 2011 19:57:34 -0000      1.226
+++ smtpd.h     25 May 2011 21:46:51 -0000
@@ -324,6 +324,7 @@ struct rule {
        }                                r_value;
 
        char                            *r_user;
+       struct mailaddr                 *r_as;
        objid_t                          r_amap;
        time_t                           r_qexpire;
 };
@@ -376,6 +377,7 @@ struct delivery_mda {
 
 struct delivery_mta {
        struct relayhost relay;
+       struct mailaddr relay_as;
 };
 
 struct delivery {


-- 
Gilles Chehade
http://www.poolp.org

Reply via email to