Re: [courier-users] hosteddomains and aliases capitalization

This is a discussion on Re: [courier-users] hosteddomains and aliases capitalization within the Courier-Imap forums, part of the Mail Servers and Related category; This is a multi-part message in MIME format. --------------080907080602050203020303 Content-Type: text/plain; charset=ISO-8859-1; format=flowed ...


Go Back   Usenet Forums > Mail Servers and Related > Courier-Imap

FAQ Members List Calendar Search Today's Posts Mark Forums Read
  #1 (permalink)  
Old 10-27-2006
Alessandro Vesely
 
Posts: n/a
Default Re: [courier-users] hosteddomains and aliases capitalization

This is a multi-part message in MIME format.
--------------080907080602050203020303
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit

David Gomillion wrote:
> charles uchu wrote:
>>
>> I think it is understood that based on the current code in courier that,
>> even if there is an aliased domain set in hosteddomains, that you must
>> again explicitly state this aliasing in the aliases file for addresses
>> that are not mailboxes.

>
> To cut down on the confusion, I always recommend creating a hosted
> domain, and then create actual mailboxes for each alias I want to
> create. In it I create a .courier file to forward the mail where ever I
> want it to go.


That way one can trace which alias has been matched. Although technically
it is a full blown mailbox, it would be unfair to count it as such for
administrative purposes.

> The ONLY aliases I create in the global alias file are
> those required by the system (like root, postmaster, etc).


However,it is annoying to maintain a bunch of aliases for each domain.
I have a script structured more or less like so:

LCLOCAL=`echo $LOCAL | tr '[A-Z]' '[a-z]'`
case $LCLOCAL in
webmaster|postmaster|admin|abuse|operator|sys|syst em|root)
NEWADDR="me@my.domain";;
*)
NEWADDR="";;
esac
if [ "$NEWADDR" = "" ]; then
case $HOST in
domain1*)
# per domain catchall policy...;;
# ...
esac
fi

if [ "$NEWADDR" = "" ]; then
exit 64
fi

printf "$NEWADDR\n"
exit 0

> It's a little extra work, but in the end, I opt for simplicity and
> maintainability. And it's very easy to script with bash...


Yes. After some years spent trying to match rcptfilters with a dynamic
delivery instruction calling the above script from .courier-default,
I finally coded the attached replacement for maildropfilter to run the
same script in either case.

I'd propose to drop it in a miscellanea "contrib" directory, if Courier
had one...


--------------080907080602050203020303
Content-Type: text/plain;
name="rcptfilter.c"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="rcptfilter.c"

/*
* rcptfilter.c - written by vesely in milan on 8 aug 2006
*
* Run rcptfilter.sh
* gcc -W -O -DNDEBUG -o /usr/local/sbin/rcptfilter rcptfilter.c
* gcc -W -Wall -Wno-parentheses -O0 -g -o rcptfilter rcptfilter.c
*/

#define SCRIPTFILE "rcptfilter.sh"

static char const usage[] =
"usage:\n"
"\trcptfilter -h\n"
"\trcptfilter -D uid/gid -M rcptfilter[-ext] ...\n"
"The first format is only useful to print this note.\n"
"The second format is used by Courier's local output module if the\n"
"maildropfilter configuration file contains the path of this executable.\n"
"In this case, rcptfilter changes directory to HOME and looks for file\n"
"\"" SCRIPTFILE "\" and runs it (with null input and output, logged error)\n"
"and then returns an exit code of 0 if the script exits rc < 50, 1 otherwise.\n"
"The script will have argument $1 set to \"RCPT\" and the other arguments\n"
"set to whatever was passed to rcptfilter as ellipsis (...). The variables\n"
"LOCAL and HOST will be set from ext. The rest of the environment remains.";

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <syslog.h>
#include <ctype.h>
#include <errno.h>
#include <assert.h>

static volatile int
signal_child = 0,
signal_timed_out = 0,
signal_break = 0;

static void sig_catcher(int sig)
{
#if !defined(NDEBUG)
char buf[80];
unsigned s = snprintf(buf, sizeof buf,
"rcptfilter[%d]: received signal %d\n",
(int)getpid(), sig);
if (s >= sizeof buf)
{
buf[sizeof buf - 1] = '\n';
s = sizeof buf;
}
write(2, buf, s);
#endif
switch(sig)
{
case SIGALRM:
signal_timed_out = 1;
break;

case SIGHUP:
case SIGPIPE:
case SIGINT:
case SIGQUIT:
case SIGTERM:
signal_break = 1;
break;

case SIGCHLD:
signal_child = 1;
break;

default:
break;
}
}

#if 0
static void reset_signal(void)
{
struct sigaction act;
memset(&act, 0, sizeof act);
sigemptyset(&act.sa_mask);
act.sa_handler = SIG_DFL;

sigaction(SIGALRM, &act, NULL);
sigaction(SIGPIPE, &act, NULL);
sigaction(SIGINT, &act, NULL);
sigaction(SIGTERM, &act, NULL);
sigaction(SIGHUP, &act, NULL);
sigaction(SIGCHLD, &act, NULL);
}
#endif

static void set_signal(void)
{
struct sigaction act;
memset(&act, 0, sizeof act);
sigemptyset(&act.sa_mask);

act.sa_handler = sig_catcher;
sigaction(SIGALRM, &act, NULL);
sigaction(SIGPIPE, &act, NULL);
sigaction(SIGINT, &act, NULL);
sigaction(SIGTERM, &act, NULL);
sigaction(SIGHUP, &act, NULL);
sigaction(SIGCHLD, &act, NULL);
}

static void addtoenv(char const *name, char const *value)
{
char *freeonexit = (char*)malloc(strlen(name) + strlen(value) + 1);
if (freeonexit)
putenv(strcat(strcpy(freeonexit, name), value));
}

static int run_script(char const *ext, char *argv[], char const *home)
{
int rtc = 0;
char *local = strdup(ext);
if (local)
{
int err[2];
char *host = strchr(local, '@');

if (host)
*host++ = 0;
else
host = "";
addtoenv("HOST=", host);
addtoenv("LOCAL=", local);
free(local);

if (pipe(err) < 0)
syslog(LOG_CRIT, "Cannot open pipe: %s\n", strerror(errno));
else
{
pid_t const pid = fork();
if (pid < 0)
syslog(LOG_CRIT, "Cannot fork: %s\n", strerror(errno));
else if (pid)
{
char buf[2048], *next = &buf[0];
char *const first = &buf[0], *const last = &buf[sizeof buf - 2];

close(err[1]);
alarm(30);
last[1] = 0; // terminator on forced newline
while (signal_timed_out == 0 &&
signal_break == 0 &&
signal_child == 0)
{
int rd = read(err[0], next, last - next);
#if !defined NDEBUG
printf("rd=%2d, next=%2d\n", rd, next - first);
#endif
if (rd > 0)
{
char *p = first, *br;
next += rd;

*next = next == last? '\n': 0; // force newline if full

while ((br = strchr(p, '\n')) != NULL)
{
int level = LOG_CRIT;
*br = 0;

/*
* e.g., "##This is a warning\n"
*/
while (*p == '#' && level < LOG_DEBUG)
++p, ++level;

if (*p) syslog(level, "script: %s\n", p);
p = br + (br < last); // +1 if not forced newline
assert(first <= p && p <= next);
}

memmove(first, p, next - p);
next -= p - first;
assert(first <= next && next < last);
}
else if (rd == 0 || errno != EINTR && errno != EAGAIN)
{
if (rd)
syslog(LOG_CRIT, "Pipe broken: %s\n", strerror(errno));
break;
}
}
alarm(0);
if (signal_timed_out || signal_break)
{
kill(pid, SIGTERM);
}
close(err[0]);

for (;;)
{
int status;
pid_t wpid = wait(&status);
if (wpid < 0 && errno != EAGAIN && errno != EINTR)
{
syslog(LOG_CRIT,
"Cannot wait %s/" SCRIPTFILE "[%u]: %s\n",
home, (unsigned)wpid, strerror(errno));
break;
}
else if (wpid == pid)
{
if (WIFEXITED(status))
{
int level, s_rtc = WEXITSTATUS(status);
switch (s_rtc)
{
case 0: case 64: case 99: level = LOG_DEBUG; break;
default: level = LOG_CRIT; break;
}
rtc = s_rtc > 50;
syslog(level,
"%s/" SCRIPTFILE " with %s exited %d, rtc=%d\n",
home, ext, s_rtc, rtc);
}
else if (WIFSIGNALED(status))
{
syslog(LOG_CRIT,
"%s/" SCRIPTFILE " terminated with signal %d, rtc=%d\n",
home, WTERMSIG(status), rtc);
}
else continue; // stopped?

break;
}
}
}
else // child process
{
close(0);
open("/dev/null", O_RDONLY);
close(1);
open("/dev/null", O_WRONLY);
close(2);
dup(err[1]);
close(err[0]);
close(err[1]);
closelog();
execv(SCRIPTFILE, argv);
syslog(LOG_MAIL|LOG_CRIT, "rcptfilter: cannot execv: %s\n",
strerror(errno));
exit(0);
}
}

}
return rtc;
}

int main(int argc, char *argv[])
{
int rtc = 0;
int i, uid = 0, gid = 0, err = 0;
char *ext = NULL, *home = getenv("HOME");
static char const argerror[] = "invoked with wrong argument: ";

char *xargv[32];
size_t xargc = 0;

openlog("rcptfilter", LOG_PID, LOG_MAIL);
xargv[xargc++] = SCRIPTFILE;
xargv[xargc++] = "RCPT";

for (i = 1; i < argc; ++i)
{
char *a = argv[i];
int pass_it = 1;

if (*a == '-')
{
pass_it = 0;
switch (*++a)
{
case 'D':
if (i + 1 >= argc)
{
syslog(LOG_CRIT, "%s-D requires a value\n", argerror);
++err;
}
else
{
char *t = NULL;
a = argv[++i];
uid = strtoul(a, &t, 10);
if (t && *t == '/')
{
gid = strtoul(t + 1, &t, 10);
if (t && *t) t = NULL;
}
else t = NULL;
if (t == NULL)
{
syslog(LOG_CRIT, "%suidgid is %s\n", argerror, a);
++err;
}
}
break;

case 'M':
if (i + 1 >= argc)
{
syslog(LOG_CRIT, "%s-M requires a value\n", argerror);
++err;
}
else if (strncmp(a = argv[++i],
"rcptfilter" , sizeof "rcptfilter" - 1) != 0)
{
syslog(LOG_CRIT, "%s-M with value %s\n", argerror, a);
++err;
}
else
{
ext = strchr(a, '-');
if (ext)
++ext;
else
ext = "";
}
break;

case 'h':
puts(usage);
return 0;

default:
pass_it = 1;
break;
}
}

if (pass_it && xargc + 1 < sizeof xargv/ sizeof xargv[0])
{
xargv[xargc++] = a;
}
}

xargv[xargc] = NULL;

if (geteuid() == 0 && (uid || gid))
{
if (gid) setgid(gid);
setuid(uid);
}

set_signal();
if (home && ext)
{
struct stat buf;
uid_t const me = geteuid();
gid_t const myg = getegid();

if (chdir(home))
{
syslog(LOG_CRIT, "Cannot chdir to %s: %s\n",
home, strerror(errno));
}
else if (stat(SCRIPTFILE, &buf) != 0)
{
if (errno != ENOENT)
syslog(LOG_CRIT, "Cannot stat %s/" SCRIPTFILE ": %s\n",
home, strerror(errno));
}
else if (!S_ISREG(buf.st_mode) || !(
((S_IXUSR & buf.st_mode) && (me == 0 || me == buf.st_uid)) ||
((S_IXGRP & buf.st_mode) && (me == 0 || myg == buf.st_gid)) ||
(S_IXOTH & buf.st_mode)))
{
syslog(LOG_INFO, "%s/" SCRIPTFILE " not executable by %d/%d\n",
home, (int)me, (int)myg);
}
else
{
rtc = run_script(ext, xargv, home);
}
}
else
{
syslog(LOG_CRIT, "%smissing %s%s%s\n", argerror,
home ? "" : "HOME env variable",
home || ext ? "" : " and ",
ext ? "" : "-M argument");
}

return rtc;
}

--------------080907080602050203020303
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=...057&dat=121642
--------------080907080602050203020303
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

_______________________________________________
courier-users mailing list
courier-users@lists.sourceforge.net
Unsubscribe: https://lists.sourceforge.net/lists/.../courier-users

--------------080907080602050203020303--

Reply With Quote
Reply
Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are Off
[IMG] code is Off
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On



All times are GMT +1. The time now is 01:26 PM.


Powered by vBulletin® Version 3.7.3
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Content Relevant URLs by vBSEO 3.0.0