On Mon, May 22, 2000 at 10:21:23AM -0500, Ed Woodson wrote: > I have been scanning the list archives for hours, trying to figure out how I > can accomplish this: > > I have a qmail server up and running perfectly, doing selective relaying for > our internal network only. I would like to further limit this for selected > users, if possible. My ultimate goal is to have two classes of users, one > class which can use qmail for both "external" and "internal" mail, and > another class which is limited to "internal" mail only. > > Please correct me if I am wrong, but it appears that my choices are: > > 1) selectively relay based upon IP address > 2) control relaying by envelope sender (using the "relaymailfrom" patch) > > Is it possible to combine the two? For example, can I allow relaying from > my own network only with (1), and also use the "relaymailfrom" patch to > restrict this _further_ to messages with a certain envelope sender? > > I know that (2) is closer to what I am trying to do, but it seems to add to > those allowed to relay, not to further restrict it. Also, I know that it is > easy for a user to forge the envelope sender, but I am not worried about > that (as long as I can still be assured it is coming from our local > network). Someone else asked for this a long time ago, and I whipped up the following patch which should help you. Chris ------------------------ This patch lets you control SMTP relaying based on envelope sender address. Note that this is not secure--it's trivial to forge a message's envelope sender. But it's something that people have asked for, and combined with tarpitting and running your SMTP daemon on a non-standard port, it may give you an acceptable level of safety. As with the unpatched version of qmail-smtpd, relaying is allowed whenever RELAYCLIENT is set. This patch adds a control file called relaymailfrom; envelope senders listed in the file will also be allowed to relay. Entries in relaymailfrom can be e-mail addresses, or just the domain (with the @ sign). So if I want [EMAIL PROTECTED] and anyone in domain2.com to be able to relay, my control/relaymailfrom file would contain: [EMAIL PROTECTED] @domain2.com RELAYBYADDRESS must be set in qmail-smtpd's environment in order for relaying by envelope sender to be allowed. So, for example, if you wanted to allow anyone at 192.168.15.* to relay through your server as long as his envelope sender address was in your relaymailfrom file, you'd have the following in your tcpserver rules file (assuming you're using tcpserver and not inetd): 192.168.15.:allow,RELAYBYADDRESS="" --- qmail-smtpd.c.orig Mon Jun 15 06:53:16 1998 +++ qmail-smtpd.c Wed May 5 23:31:23 1999 @@ -81,6 +81,7 @@ char *remoteinfo; char *local; char *relayclient; +char *relayok; stralloc helohost = {0}; char *fakehelo; /* pointer into helohost, or 0 */ @@ -96,6 +97,9 @@ int bmfok = 0; stralloc bmf = {0}; struct constmap mapbmf; +int rmfok = 0; +stralloc rmf = {0}; +struct constmap maprmf; void setup() { @@ -117,6 +121,13 @@ if (bmfok) if (!constmap_init(&mapbmf,bmf.s,bmf.len,0)) die_nomem(); + if ( env_get("RELAYBYADDRESS") ) { + rmfok = control_readfile(&rmf,"control/relaymailfrom",0); + if (rmfok == -1) die_control(); + if (rmfok) + if (!constmap_init(&maprmf,rmf.s,rmf.len,0)) die_nomem(); + } + if (control_readint(&databytes,"control/databytes") == -1) die_control(); x = env_get("DATABYTES"); if (x) { scan_ulong(x,&u); databytes = u; } @@ -130,7 +141,7 @@ remotehost = env_get("TCPREMOTEHOST"); if (!remotehost) remotehost = "unknown"; remoteinfo = env_get("TCPREMOTEINFO"); - relayclient = env_get("RELAYCLIENT"); + relayok = relayclient = env_get("RELAYCLIENT"); dohelo(remotehost); } @@ -208,6 +219,17 @@ return 0; } +int rmfcheck() +{ + int j; + if (!rmfok) return 0; + if (constmap(&maprmf,addr.s,addr.len - 1)) return 1; + j = byte_rchr(addr.s,addr.len,'@'); + if (j < addr.len) + if (constmap(&maprmf,addr.s + j,addr.len - j - 1)) return 1; + return 0; +} + int addrallowed() { int r; @@ -241,6 +263,7 @@ { if (!addrparse(arg)) { err_syntax(); return; } flagbarf = bmfcheck(); + if (!relayok) if (rmfcheck()) relayclient = ""; else relayclient = 0; seenmail = 1; if (!stralloc_copys(&rcptto,"")) die_nomem(); if (!stralloc_copys(&mailfrom,addr.s)) die_nomem();