diff options
-rw-r--r-- | vda/postfix-2.4.6-vda-ng-r2.patch.gz | bin | 12397 -> 0 bytes | |||
-rw-r--r-- | vda/postfix-2.5.1-vda-ng-r1.patch.gz | bin | 0 -> 28964 bytes | |||
-rw-r--r-- | vda/postfix-2.5.1-vda-ng.patch | 2084 |
3 files changed, 2031 insertions, 53 deletions
diff --git a/vda/postfix-2.4.6-vda-ng-r2.patch.gz b/vda/postfix-2.4.6-vda-ng-r2.patch.gz Binary files differdeleted file mode 100644 index 714653f..0000000 --- a/vda/postfix-2.4.6-vda-ng-r2.patch.gz +++ /dev/null diff --git a/vda/postfix-2.5.1-vda-ng-r1.patch.gz b/vda/postfix-2.5.1-vda-ng-r1.patch.gz Binary files differnew file mode 100644 index 0000000..e16ea02 --- /dev/null +++ b/vda/postfix-2.5.1-vda-ng-r1.patch.gz diff --git a/vda/postfix-2.5.1-vda-ng.patch b/vda/postfix-2.5.1-vda-ng.patch index f73fafe..f3b5731 100644 --- a/vda/postfix-2.5.1-vda-ng.patch +++ b/vda/postfix-2.5.1-vda-ng.patch @@ -1,6 +1,6 @@ -diff -Nru postfix-2.4.6/README_FILES/VDA_README postfix-2.4.6-vda-ng/README_FILES/VDA_README ---- postfix-2.4.6/README_FILES/VDA_README 1970-01-01 01:00:00.000000000 +0100 -+++ postfix-2.4.6-vda-ng/README_FILES/VDA_README 2007-11-24 12:48:53.000000000 +0100 +diff -Nru postfix-2.5.1/README_FILES/VDA_README postfix-2.5.1-vda-ng/README_FILES/VDA_README +--- postfix-2.5.1/README_FILES/VDA_README 1970-01-01 01:00:00.000000000 +0100 ++++ postfix-2.5.1-vda-ng/README_FILES/VDA_README 2008-03-15 15:06:00.007734561 +0100 @@ -0,0 +1,97 @@ +Installation: + @@ -99,10 +99,1453 @@ diff -Nru postfix-2.4.6/README_FILES/VDA_README postfix-2.4.6-vda-ng/README_FILE +user2@domain.com.br # M2007022617 /^subject:.*Viagra.*/m REJECT /^subject:.*trash.*/m MOVE SpamFolder /^subject:.*pharmacy.*/m DISCARD + +More informations can be found at http://vda.sourceforge.net -diff -Nru postfix-2.4.6/src/global/mail_params.h postfix-2.4.6-vda-ng/src/global/mail_params.h ---- postfix-2.4.6/src/global/mail_params.h 2007-07-11 01:47:45.000000000 +0200 -+++ postfix-2.4.6-vda-ng/src/global/mail_params.h 2007-11-24 12:48:53.000000000 +0100 -@@ -2106,6 +2106,54 @@ +diff -Nru postfix-2.5.1/postfix-2.4.6-vda-ng.patch postfix-2.5.1-vda-ng/postfix-2.4.6-vda-ng.patch +--- postfix-2.5.1/postfix-2.4.6-vda-ng.patch 1970-01-01 01:00:00.000000000 +0100 ++++ postfix-2.5.1-vda-ng/postfix-2.4.6-vda-ng.patch 2008-03-15 15:05:52.167991798 +0100 +@@ -0,0 +1,1439 @@ ++diff -Nru postfix-2.4.6/README_FILES/VDA_README postfix-2.4.6-vda-ng/README_FILES/VDA_README ++--- postfix-2.4.6/README_FILES/VDA_README 1970-01-01 01:00:00.000000000 +0100 +++++ postfix-2.4.6-vda-ng/README_FILES/VDA_README 2007-11-24 12:48:53.000000000 +0100 ++@@ -0,0 +1,97 @@ +++Installation: +++ +++1 - Get the Postfix source code ( http://www.postfix.org/ ) +++2 - Get this software ( http://vda.sourceforge.net ) for your Postfix version +++3 - Unpack the source code: tar -xvzf postfix-VERSION.tar.gz +++4 - Unpack the patch: gunzip postfix-VERSION-vda-ng-rREV.patch.gz +++5 - Apply the patch: cd postfix-VERSION; patch -p1 < ../postfix-VERSION-vda-ng-rREV.patch +++6 - Configure +++7 - Make +++ +++Configuration: +++ +++#### Postfix main.cf +++ +++# I use only virtual as local delivery +++mailbox_transport = virtual +++ +++# Base directory where the mailboxes are located +++virtual_mailbox_base = /var/virtualmail +++ +++# Virtual users maps +++virtual_mailbox_maps = hash:/etc/postfix/vmailbox +++transport_maps = hash:/etc/postfix/vtransport +++ +++# Minimal permitted UID value (for virtual_uid_maps) +++virtual_minimum_uid = 1000 +++ +++# GIDs and UIDs to run as +++# Can also be stored in hash, mysql, ... +++virtual_uid_maps = static:4000 +++virtual_gid_maps = static:4000 +++ +++# A maximum size limit for a mailbox +++virtual_mailbox_limit = 100000000 +++ +++# Quota values maps +++virtual_mailbox_limit_maps = hash:/etc/postfix/vquota +++ +++# Limit only the INBOX +++# (useful for when you have IMAP users) +++virtual_mailbox_limit_inbox = no +++ +++# Enable limits smaller than maximum message size +++virtual_mailbox_limit_override = yes +++ +++# Enable Maildir++ extensions for faster maildir quota calculation +++# (maildirsize file and ",S=<size>" filename extension) +++# Needs Maildir++ compatible IMAP servers, like Courier-IMAP +++virtual_maildir_extended = yes +++ +++# Always bounce the message when quota reached +++virtual_overquota_bounce = yes +++ +++# Custom message to send when bouncing +++#virtual_maildir_limit_message = "Sorry, maximum quota reached!" +++ +++# Custom message maps for the bounces +++#virtual_maildir_limit_message_maps = hash:/etc/postfix/vmsg +++ +++# Also count the Trash folder when calculating quotas? +++virtual_trash_count = yes +++ +++# The name of the Trash folder +++# (if it doesn't need to be calculated) +++#virtual_trash_name = ".Trash" +++ +++# Enable the Maildirfilter feature +++virtual_maildir_filter = yes +++ +++# Maildirfilter maps +++virtual_maildir_filter_maps = hash:/etc/postfix/vfilter +++ +++#### Mailbox users file - vmailbox +++user@domain.com.br /path/to/mailbox - path relative to virtual_mailbox_base +++user1@domain.com.br /domain.com.br/user1 - no trailing slash, user has a MAILBOX +++user2@domain.com.br /domain.com.br/user2 - no trailing slash, user has a MAILBOX +++user1@domain.net.br /domain.net.br/user1/ - trailing slash, user has a MAILDIR +++user2@domain.net.br /domain.net.br/user2/ - trailing slash, user has a MAILDIR +++ +++#### Quota users file - vquota +++user@domain.com.br QUOTA IN BYTES +++user1@domain.com.br 2048000 +++user2@domain.com.br 2048000 +++user1@domain.net.br 5192000 +++user2@domain.net.br 0 - NO QUOTA +++ +++#### Maildirfilter file - vfilter +++# ATTENTION: the syntax for maildirfilter values is the following: +++# the # sign, followed by a space, followed by a M (uppercase), then a modification time value +++# (you need to change this when you change the regexps) made of a maximum of 10 digits, then a +++# space again and an arbitrary number of regexps (a regexp always starts with /^ and ends with +++# a space) and their corresponding actions +++user@domain.com.br # M<timestamp> regexp1 action1 regexp2 action2 ... +++user1@domain.net.br # M2007022701 /^subject:.*BAD.*/m DISCARD /^from:.*user@domain.com.br*/m MOVE Trash +++user2@domain.com.br # M2007022617 /^subject:.*Viagra.*/m REJECT /^subject:.*trash.*/m MOVE SpamFolder /^subject:.*pharmacy.*/m DISCARD +++ +++More informations can be found at http://vda.sourceforge.net ++diff -Nru postfix-2.4.6/src/global/mail_params.h postfix-2.4.6-vda-ng/src/global/mail_params.h ++--- postfix-2.4.6/src/global/mail_params.h 2007-07-11 01:47:45.000000000 +0200 +++++ postfix-2.4.6-vda-ng/src/global/mail_params.h 2007-11-24 12:48:53.000000000 +0100 ++@@ -2106,6 +2106,54 @@ ++ #define DEF_VIRT_GID_MAPS "" ++ extern char *var_virt_gid_maps; ++ +++#define VAR_VIRT_MAILBOX_LIMIT_MAPS "virtual_mailbox_limit_maps" +++#define DEF_VIRT_MAILBOX_LIMIT_MAPS "" +++extern char *var_virt_mailbox_limit_maps; +++ +++#define VAR_VIRT_MAILBOX_LIMIT_INBOX "virtual_mailbox_limit_inbox" +++#define DEF_VIRT_MAILBOX_LIMIT_INBOX 0 +++extern bool var_virt_mailbox_limit_inbox; +++ +++#define VAR_VIRT_MAILBOX_LIMIT_OVERRIDE "virtual_mailbox_limit_override" +++#define DEF_VIRT_MAILBOX_LIMIT_OVERRIDE 0 +++extern bool var_virt_mailbox_limit_override; +++ +++#define VAR_VIRT_MAILDIR_EXTENDED "virtual_maildir_extended" +++#define DEF_VIRT_MAILDIR_EXTENDED 0 +++extern bool var_virt_maildir_extended; +++ +++#define VAR_VIRT_OVERQUOTA_BOUNCE "virtual_overquota_bounce" +++#define DEF_VIRT_OVERQUOTA_BOUNCE 0 +++extern bool var_virt_overquota_bounce; +++ +++#define VAR_VIRT_MAILDIR_LIMIT_MESSAGE "virtual_maildir_limit_message" +++#define DEF_VIRT_MAILDIR_LIMIT_MESSAGE "Sorry, the user's maildir has overdrawn his diskspace quota, please try again later." +++extern char *var_virt_maildir_limit_message; +++ +++#define VAR_VIRT_MAILDIR_LIMIT_MESSAGE_MAPS "virtual_maildir_limit_message_maps" +++#define DEF_VIRT_MAILDIR_LIMIT_MESSAGE_MAPS "" +++extern char *var_virt_maildir_limit_message_maps; +++ +++#define VAR_VIRT_MAILDIR_SUFFIX "virtual_maildir_suffix" +++#define DEF_VIRT_MAILDIR_SUFFIX "" +++extern char *var_virt_maildir_suffix; +++ +++#define VAR_VIRT_TRASH_COUNT "virtual_trash_count" +++#define DEF_VIRT_TRASH_COUNT 0 +++extern bool var_virt_trash_count; +++ +++#define VAR_VIRT_TRASH_NAME "virtual_trash_name" +++#define DEF_VIRT_TRASH_NAME ".Trash" +++extern char *var_virt_trash_name; +++ +++#define VAR_VIRT_MAILDIR_FILTER "virtual_maildir_filter" +++#define DEF_VIRT_MAILDIR_FILTER 0 +++extern bool var_virt_maildir_filter; +++ +++#define VAR_VIRT_MAILDIR_FILTER_MAPS "virtual_maildir_filter_maps" +++#define DEF_VIRT_MAILDIR_FILTER_MAPS "" +++extern char *var_virt_maildir_filter_maps; +++ ++ #define VAR_VIRT_MINUID "virtual_minimum_uid" ++ #define DEF_VIRT_MINUID 100 ++ extern int var_virt_minimum_uid; ++diff -Nru postfix-2.4.6/src/util/file_limit.c postfix-2.4.6-vda-ng/src/util/file_limit.c ++--- postfix-2.4.6/src/util/file_limit.c 2003-10-22 20:48:36.000000000 +0200 +++++ postfix-2.4.6-vda-ng/src/util/file_limit.c 2007-11-24 12:48:53.000000000 +0100 ++@@ -85,7 +85,11 @@ ++ #else ++ struct rlimit rlim; ++ ++- rlim.rlim_cur = rlim.rlim_max = limit; +++ /* rlim_max can only be changed by root. */ +++ if (getrlimit(RLIMIT_FSIZE, &rlim) < 0) +++ msg_fatal("getrlimit: %m"); +++ rlim.rlim_cur = limit; +++ ++ if (setrlimit(RLIMIT_FSIZE, &rlim) < 0) ++ msg_fatal("setrlimit: %m"); ++ #ifdef SIGXFSZ ++diff -Nru postfix-2.4.6/src/virtual/mailbox.c postfix-2.4.6-vda-ng/src/virtual/mailbox.c ++--- postfix-2.4.6/src/virtual/mailbox.c 2006-06-26 14:59:19.000000000 +0200 +++++ postfix-2.4.6-vda-ng/src/virtual/mailbox.c 2007-11-26 12:30:21.000000000 +0100 ++@@ -70,6 +70,70 @@ ++ #define YES 1 ++ #define NO 0 ++ +++/* change_mailbox_limit - change limit for mailbox file */ +++static int change_mailbox_limit(LOCAL_STATE state, USER_ATTR usr_attr) +++{ +++ char *myname = "change_mailbox_limit"; +++ const char *limit_res; +++ long n = 0; +++ int status = NO; +++ +++ /* +++ * Look up the virtual mailbox limit size for this user. +++ * Fall back to virtual_mailbox_limit in case lookup failed. +++ * If virtual mailbox limit size is negative, fall back to virtual_mailbox_limit. +++ * If it's 0, set the mailbox limit to 0, which means unlimited. +++ * If it's more than 0 (positive int), check if the value is smaller than the maximum message size, +++ * if it is and the virtual mailbox limit can't be overridden, fall back to virtual_mailbox_limit and +++ * warn the user, else use the value directly as the mailbox limit. +++ */ +++ if (*var_virt_mailbox_limit_maps != 0 && (limit_res = mail_addr_find(virtual_mailbox_limit_maps, state.msg_attr.user, (char **) NULL)) != 0) { +++ n = atol(limit_res); +++ if (n > 0) { +++ if ((n < var_message_limit) && (!var_virt_mailbox_limit_override)) { +++ set_file_limit(var_virt_mailbox_limit); +++ status = NO; +++ +++ msg_warn("%s: recipient %s - virtual mailbox limit is " +++ "smaller than %s in %s - falling back to %s", +++ myname, +++ state.msg_attr.user, +++ VAR_MESSAGE_LIMIT, +++ virtual_mailbox_limit_maps->title, +++ VAR_VIRT_MAILBOX_LIMIT); +++ } +++ else { +++ set_file_limit((off_t) n); +++ status = YES; +++ +++ if (msg_verbose) +++ msg_info("%s: set virtual mailbox limit size for %s to %ld", +++ myname, usr_attr.mailbox, n); +++ } +++ } +++ else if (n == 0) { +++ set_file_limit(OFF_T_MAX); +++ status = YES; +++ +++ if (msg_verbose) +++ msg_info("%s: set virtual mailbox limit size for %s to %ld", +++ myname, usr_attr.mailbox, OFF_T_MAX); +++ } +++ else { +++ /* Invalid limit size (negative). Use default virtual_mailbox_limit. */ +++ set_file_limit(var_virt_mailbox_limit); +++ status = NO; +++ } +++ } +++ else { +++ /* There is no limit in the maps. Use default virtual_mailbox_limit. */ +++ set_file_limit(var_virt_mailbox_limit); +++ status = NO; +++ } +++ +++ return(status); +++} +++ ++ /* deliver_mailbox_file - deliver to recipient mailbox */ ++ ++ static int deliver_mailbox_file(LOCAL_STATE state, USER_ATTR usr_attr) ++@@ -207,62 +271,72 @@ ++ * Look up the mailbox owner rights. Defer in case of trouble. ++ */ ++ uid_res = mail_addr_find(virtual_uid_maps, state.msg_attr.user, ++- IGNORE_EXTENSION); ++- if (uid_res == 0) { ++- msg_warn("recipient %s: not found in %s", ++- state.msg_attr.user, virtual_uid_maps->title); ++- dsb_simple(why, "4.3.5", "mail system configuration error"); ++- *statusp = defer_append(BOUNCE_FLAGS(state.request), ++- BOUNCE_ATTR(state.msg_attr)); ++- RETURN(YES); +++ IGNORE_EXTENSION); +++ +++ if ((uid_res = mail_addr_find(virtual_uid_maps, state.msg_attr.user, (char **) 0)) == 0) { +++ if ((uid_res = maps_find(virtual_uid_maps, strchr(state.msg_attr.user, '@'), DICT_FLAG_FIXED)) == 0) { +++ msg_warn("recipient %s: not found in %s", state.msg_attr.user, virtual_uid_maps->title); +++ dsb_simple(why, "4.3.5", "mail system configuration error"); +++ *statusp = defer_append(BOUNCE_FLAGS(state.request), BOUNCE_ATTR(state.msg_attr)); +++ RETURN(YES); +++ } ++ } +++ ++ if ((n = atol(uid_res)) < var_virt_minimum_uid) { ++- msg_warn("recipient %s: bad uid %s in %s", ++- state.msg_attr.user, uid_res, virtual_uid_maps->title); ++- dsb_simple(why, "4.3.5", "mail system configuration error"); ++- *statusp = defer_append(BOUNCE_FLAGS(state.request), ++- BOUNCE_ATTR(state.msg_attr)); ++- RETURN(YES); +++ msg_warn("recipient %s: bad uid %s in %s", state.msg_attr.user, uid_res, virtual_uid_maps->title); +++ dsb_simple(why, "4.3.5", "mail system configuration error"); +++ *statusp = defer_append(BOUNCE_FLAGS(state.request), BOUNCE_ATTR(state.msg_attr)); +++ RETURN(YES); ++ } +++ ++ usr_attr.uid = (uid_t) n; ++ ++ /* ++ * Look up the mailbox group rights. Defer in case of trouble. ++ */ ++ gid_res = mail_addr_find(virtual_gid_maps, state.msg_attr.user, ++- IGNORE_EXTENSION); ++- if (gid_res == 0) { ++- msg_warn("recipient %s: not found in %s", ++- state.msg_attr.user, virtual_gid_maps->title); ++- dsb_simple(why, "4.3.5", "mail system configuration error"); ++- *statusp = defer_append(BOUNCE_FLAGS(state.request), ++- BOUNCE_ATTR(state.msg_attr)); ++- RETURN(YES); +++ IGNORE_EXTENSION); +++ +++ if ((gid_res = mail_addr_find(virtual_gid_maps, state.msg_attr.user, (char **) 0)) == 0) { +++ if ((gid_res = maps_find(virtual_gid_maps, strchr(state.msg_attr.user, '@'), DICT_FLAG_FIXED)) == 0) { +++ msg_warn("recipient %s: not found in %s", state.msg_attr.user, virtual_gid_maps->title); +++ dsb_simple(why, "4.3.5", "mail system configuration error"); +++ *statusp = defer_append(BOUNCE_FLAGS(state.request), BOUNCE_ATTR(state.msg_attr)); +++ RETURN(YES); +++ } ++ } +++ ++ if ((n = atol(gid_res)) <= 0) { ++- msg_warn("recipient %s: bad gid %s in %s", ++- state.msg_attr.user, gid_res, virtual_gid_maps->title); ++- dsb_simple(why, "4.3.5", "mail system configuration error"); ++- *statusp = defer_append(BOUNCE_FLAGS(state.request), ++- BOUNCE_ATTR(state.msg_attr)); ++- RETURN(YES); +++ msg_warn("recipient %s: bad gid %s in %s", state.msg_attr.user, gid_res, virtual_gid_maps->title); +++ dsb_simple(why, "4.3.5", "mail system configuration error"); +++ *statusp = defer_append(BOUNCE_FLAGS(state.request), BOUNCE_ATTR(state.msg_attr)); +++ RETURN(YES); ++ } +++ ++ usr_attr.gid = (gid_t) n; ++ ++ if (msg_verbose) ++- msg_info("%s[%d]: set user_attr: %s, uid = %u, gid = %u", ++- myname, state.level, usr_attr.mailbox, ++- (unsigned) usr_attr.uid, (unsigned) usr_attr.gid); +++ msg_info("%s[%d]: set user_attr: %s, uid = %u, gid = %u", +++ myname, state.level, usr_attr.mailbox, +++ (unsigned) usr_attr.uid, (unsigned) usr_attr.gid); ++ ++ /* ++ * Deliver to mailbox or to maildir. ++ */ ++ #define LAST_CHAR(s) (s[strlen(s) - 1]) ++ ++- if (LAST_CHAR(usr_attr.mailbox) == '/') ++- *statusp = deliver_maildir(state, usr_attr); ++- else ++- *statusp = deliver_mailbox_file(state, usr_attr); +++ if (LAST_CHAR(usr_attr.mailbox) == '/') { +++ *statusp = deliver_maildir(state, usr_attr); +++ } +++ else { +++ int changed_limit; +++ +++ changed_limit = change_mailbox_limit(state, usr_attr); +++ *statusp = deliver_mailbox_file(state, usr_attr); +++ +++ if (changed_limit) +++ set_file_limit(var_virt_mailbox_limit); +++ } ++ ++ /* ++ * Cleanup. ++diff -Nru postfix-2.4.6/src/virtual/maildir.c postfix-2.4.6-vda-ng/src/virtual/maildir.c ++--- postfix-2.4.6/src/virtual/maildir.c 2006-06-26 14:59:19.000000000 +0200 +++++ postfix-2.4.6-vda-ng/src/virtual/maildir.c 2007-11-24 13:20:57.000000000 +0100 ++@@ -63,28 +63,406 @@ ++ #include <mbox_open.h> ++ #include <dsn_util.h> ++ +++/* Patch library. */ +++ +++#include <sys/types.h> /* opendir(3), stat(2) */ +++#include <sys/stat.h> /* stat(2) */ +++#include <dirent.h> /* opendir(3) */ +++#include <unistd.h> /* stat(2) */ +++#include <stdlib.h> /* atol(3) */ +++#include <string.h> /* strrchr(3) */ +++#include <vstring_vstream.h> +++#include <dict.h> +++#include <dict_regexp.h> +++#include <ctype.h> +++#include <stdio.h> +++#include <sys_defs.h> +++#include <mail_addr_find.h> +++ ++ /* Application-specific. */ ++ ++ #include "virtual.h" ++ ++-/* deliver_maildir - delivery to maildir-style mailbox */ +++/* Maildirsize maximal size. */ +++ +++#define SIZEFILE_MAX 5120 +++ +++/* +++ * Chris Stratford <chriss@pipex.net> +++ * Read the maildirsize file to get quota info. +++ * +++ * Arguments: +++ * dirname: the maildir +++ * countptr: number of messages +++ * +++ * Returns the size of all mails as read from maildirsize, +++ * zero if it couldn't read the file. +++ */ +++static long read_maildirsize(char *dirname, long *countptr) +++{ +++ struct stat statbuf; +++ VSTRING *sizefilename = vstring_alloc(1024); +++ VSTREAM *sizefile; +++ char *p; +++ int len, first; +++ long sum = 0, count = 0; +++ +++ vstring_sprintf(sizefilename, "%s/%s", dirname, "maildirsize"); +++ +++ sizefile = vstream_fopen(STR(sizefilename), O_RDONLY, 0); +++ if (!sizefile || (stat(STR(sizefilename), &statbuf) < 0) || (statbuf.st_size > SIZEFILE_MAX)) { +++ if (sizefile) { +++ vstream_fclose(sizefile); +++ unlink(STR(sizefilename)); +++ } +++ vstring_free(sizefilename); +++ +++ return 0; +++ } +++ +++ VSTRING *sizebuf = vstring_alloc(SIZEFILE_MAX); +++ len = vstream_fread(sizefile, STR(sizebuf), SIZEFILE_MAX); +++ +++ p = STR(sizebuf); +++ *(p + len) = '\0'; +++ first = 1; +++ +++ while (*p) { +++ long n = 0, c = 0; +++ char *q = p; +++ +++ while (*p) { +++ if (*p++ == '\n') { +++ p[-1] = 0; +++ break; +++ } +++ } +++ +++ if (first) { +++ first = 0; +++ continue; +++ } +++ +++ if(sscanf(q, "%ld %ld", &n, &c) == 2) { +++ sum += n; +++ count += c; +++ } +++ else { +++ vstream_fclose(sizefile); +++ unlink(STR(sizefilename)); +++ +++ msg_warn("read_maildirsize: invalid line '%s' found in %s, removing maildirsize file", q, STR(sizefilename)); +++ +++ vstring_free(sizefilename); +++ vstring_free(sizebuf); +++ +++ return 0; +++ } +++ } +++ +++ vstream_fclose(sizefile); +++ vstring_free(sizefilename); +++ vstring_free(sizebuf); +++ +++ *countptr = count; +++ +++ return sum; +++} +++ +++/* +++ * Gives the size of the file according to the Maildir++ extension +++ * present in the filename (code taken from courier-imap). +++ * +++ * Arguments: +++ * n: filename +++ * +++ * Returns the size given in ",S=<size>" in the filename, +++ * zero if it cannot find ",S=<size>" in the filename. +++ */ +++static long maildir_parsequota(const char *n) +++{ +++ const char *o; +++ int yes = 0; ++ ++-int deliver_maildir(LOCAL_STATE state, USER_ATTR usr_attr) +++ if ((o = strrchr(n, '/')) == 0) +++ o = n; +++ +++ for (; *o; o++) { +++ if (*o == ':') +++ break; +++ } +++ +++ for (; o >= n; --o) { +++ if (*o == '/') +++ break; +++ +++ if (*o == ',' && o[1] == 'S' && o[2] == '=') { +++ yes = 1; +++ o += 3; +++ break; +++ } +++ } +++ +++ if (yes) { +++ long s = 0; +++ +++ while (*o >= '0' && *o <= '9') +++ s = s*10 + (*o++ - '0'); +++ +++ return s; +++ } +++ +++ return 0; +++} +++ +++/* +++ * Computes quota usage for a directory (taken from exim). +++ * +++ * This function is called to determine the exact quota usage of a virtual +++ * maildir box. To achieve maximum possible speed while doing this, it takes +++ * advantage of the maildirsize file and the Maildir++ extensions to filenames, +++ * when applicable and configured to be used. In all other cases it simply +++ * stats all the files as needed to get the size information. +++ * +++ * Arguments: +++ * dirname: the name of the directory +++ * countptr: where to add the file count (because this function recurses) +++ * +++ * Returns the sum of the sizes of all measurable files, +++ * zero if the directory could not be opened. +++ */ +++static long check_dir_size(char *dirname, long *countptr) +++{ +++ char *myname = "check_dir_size"; +++ DIR *dir; +++ long sum = 0; +++ struct dirent *ent; +++ struct stat statbuf; +++ +++ if (!var_virt_mailbox_limit_inbox && var_virt_maildir_extended && (sum = read_maildirsize(dirname, countptr))) { +++ if (msg_verbose) +++ msg_info("%s: maildirsize used: dir=%s sum=%ld count=%ld", myname, dirname, sum, *countptr); +++ return sum; +++ } +++ +++ dir = opendir(dirname); +++ if (dir == NULL) { +++ if (make_dirs(dirname, 0700) == 0) { /* Try to create the dirs. */ +++ dir = opendir(dirname); /* Reopen the dir. */ +++ if (dir == NULL) { +++ msg_warn("%s: cannot reopen directory: %s", myname, dirname); +++ return 0; +++ } +++ } +++ else { +++ msg_warn("%s: cannot open directory: %s", myname, dirname); +++ return 0; +++ } +++ } +++ +++ while ((ent = readdir(dir)) != NULL) { +++ char *name = ent->d_name; +++ long tmpsum = 0; +++ VSTRING *buffer; +++ +++ if (var_virt_trash_count) { +++ if(strcmp(name, ".") == 0 || strcmp(name, "..") == 0) +++ continue; +++ } +++ else { +++ if(strcmp(name, ".") == 0 || strcmp(name, "..") == 0 || strcmp(name, var_virt_trash_name) == 0) +++ continue; +++ } +++ +++ /* +++ * Here comes the real logic behind this function. +++ * Optimized to be the most efficient possible, +++ * depending on the settings given. +++ * See above for a more detailed description. +++ */ +++ if (var_virt_mailbox_limit_inbox) { +++ if (var_virt_maildir_extended && (tmpsum = maildir_parsequota(name))) { +++ sum += tmpsum; +++ (*countptr)++; +++ } +++ else { +++ buffer = vstring_alloc(1024); +++ vstring_sprintf(buffer, "%s/%s", dirname, name); +++ +++ if (stat(STR(buffer), &statbuf) < 0) { +++ vstring_free(buffer); +++ continue; +++ } +++ if ((statbuf.st_mode & S_IFREG) != 0) { +++ sum += (long) statbuf.st_size; +++ (*countptr)++; +++ } +++ +++ vstring_free(buffer); +++ } +++ } +++ else { +++ buffer = vstring_alloc(1024); +++ vstring_sprintf(buffer, "%s/%s", dirname, name); +++ +++ if (stat(STR(buffer), &statbuf) < 0) { +++ vstring_free(buffer); +++ continue; +++ } +++ if ((statbuf.st_mode & S_IFREG) != 0) { +++ if (strcmp(dirname + strlen(dirname) - 3, "new") == 0 || strcmp(dirname + strlen(dirname) - 3, "cur") == 0 || strcmp(dirname + strlen(dirname) - 3, "tmp") == 0) { +++ sum += (long) statbuf.st_size; +++ (*countptr)++; +++ } +++ } +++ else if ((statbuf.st_mode & S_IFDIR) != 0) { +++ sum += check_dir_size(STR(buffer), countptr); +++ } +++ +++ vstring_free(buffer); +++ } +++ } +++ closedir(dir); +++ +++ if (msg_verbose) +++ msg_info("%s: full scan done: dir=%s sum=%ld count=%ld", myname, dirname, sum, *countptr); +++ +++ return sum; +++} +++ +++/* Cut all occurrences of pattern from string. */ +++static char *strcut(char *str, const char *pat) +++{ +++ char *ptr, *loc, *ret; +++ ret = str; +++ loc = str; +++ +++ /* No match, return original string. */ +++ if (!strstr(loc, pat)) +++ return(str); +++ +++ while (*loc && (ptr = strstr(loc, pat))) { +++ while (loc < ptr) +++ *str++ = *loc++; +++ loc += strlen(pat); +++ } +++ +++ while (*loc) +++ *str++ = *loc++; +++ +++ *str = 0; +++ +++ return(ret); +++} +++ +++/* Check if maildirfilter file is up-to-date compared to SQL, (re)write it if not. */ +++static long sql2file(char *filename, char *user) +++{ +++ char *myname = "sql2file"; +++ char *filter_sqlres; +++ char filter_fileres[128]; +++ long sqlmtime = 0, filemtime = 0, retval = 0; +++ int filterfile, size_sqlres, i; +++ struct stat statbuf; +++ +++ if (*var_virt_maildir_filter_maps != 0) { +++ filter_sqlres = (char *) mymalloc(16000); +++ filter_sqlres = (char *) mail_addr_find(virtual_maildir_filter_maps, user, (char **) 0); +++ +++ if (filter_sqlres) { +++ strcut(filter_sqlres, "\r"); +++ if (filter_sqlres[0] == '#' && filter_sqlres[1] == ' ' && filter_sqlres[2] == 'M') { +++ size_sqlres = strlen(filter_sqlres); +++ +++ for (i = 4; i <= size_sqlres; i++) { +++ if(filter_sqlres[i] == '/' && filter_sqlres[i+1] == '^') { +++ filter_sqlres[i-1] = '\n'; +++ } +++ } +++ +++ filter_sqlres[(size_sqlres+1)] = '\0'; +++ +++ sqlmtime = atol(filter_sqlres+3); +++ retval = sqlmtime; +++ +++ filterfile = open(filename, O_RDONLY, 0); +++ if (filterfile) { +++ read(filterfile, (void *) filter_fileres, 127); +++ close(filterfile); +++ +++ filemtime = atol(filter_fileres+3); +++ } +++ +++ if (msg_verbose) +++ msg_info("%s: filter data: sql_size=%d sql_mtime=%ld file_mtime=%ld", myname, strlen(filter_sqlres), sqlmtime, filemtime); +++ } +++ if (sqlmtime != filemtime && sqlmtime != 0) { +++ if ((filterfile = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0640))) { +++ if (msg_verbose) +++ msg_info("%s: updating filter file: %s", myname, filename); +++ write(filterfile, filter_sqlres, strlen(filter_sqlres)); +++ close(filterfile); +++ } +++ else { +++ msg_warn("%s: can't create filter file: %s", myname, filename); +++ retval = 0; +++ } +++ } +++ } +++ } +++ else { +++ if (stat(filename, &statbuf) == 0) +++ retval = (long) statbuf.st_mtime; +++ if (msg_verbose) +++ msg_info("%s: processing filter file: file_mtime=%ld", myname, retval); +++ } +++ +++ return retval; +++} +++ +++/* deliver_maildir - delivery to maildir-style mailbox */ +++int deliver_maildir(LOCAL_STATE state, USER_ATTR usr_attr) ++ { ++ const char *myname = "deliver_maildir"; ++- char *newdir; ++- char *tmpdir; ++- char *curdir; ++- char *tmpfile; ++- char *newfile; +++ char *newdir; +++ char *tmpdir; +++ char *curdir; +++ char *newfile; +++ char *tmpfile; ++ DSN_BUF *why = state.msg_attr.why; ++ VSTRING *buf; ++ VSTREAM *dst; ++- int mail_copy_status; ++- int deliver_status; ++- int copy_flags; ++- struct stat st; ++- struct timeval starttime; +++ int mail_copy_status; +++ int deliver_status; +++ int copy_flags; +++ struct stat st; +++ struct timeval starttime; +++ +++ /* Maildir Quota. */ +++ const char *limit_res; /* Limit from map. */ +++ char *sizefilename = (char *) 0; /* Maildirsize file name. */ +++ VSTRING *filequota; /* Quota setting from the maildirsize file. */ +++ VSTREAM *sizefile; /* Maildirsize file handle. */ +++ long n = 0; /* Limit in long integer format. */ +++ long saved_count = 0; /* The total number of files. */ +++ long saved_size = 0; /* The total quota of all files. */ +++ struct stat mail_stat; /* To check the size of the mail to be written. */ +++ struct stat sizefile_stat; /* To check the size of the maildirsize file. */ +++ time_t tm; /* To check the age of the maildirsize file. */ +++ +++ /* Maildir Filters. */ +++ const char *value, *cmd_text; /* Filter values. */ +++ char *filtername; +++ char *header; +++ char *bkpnewfile; +++ char *mdffilename = (char *) 0; /* Maildirfolder file name. */ +++ VSTRING *fltstr; +++ VSTREAM *tmpfilter; +++ VSTREAM *mdffile; /* Maildirfolder file handle. */ +++ DICT *FILTERS; +++ long sqlmtime; /* Latest modification time from sql2file(). */ +++ int cmd_len; +++ struct stat mdffile_stat; /* To check if the maildirfolder file exists. */ ++ ++ GETTIMEOFDAY(&starttime); ++ ++@@ -93,15 +471,14 @@ ++ */ ++ state.level++; ++ if (msg_verbose) ++- MSG_LOG_STATE(myname, state); +++ MSG_LOG_STATE(myname, state); ++ ++ /* ++ * Don't deliver trace-only requests. ++ */ ++ if (DEL_REQ_TRACE_ONLY(state.request->flags)) { ++- dsb_simple(why, "2.0.0", "delivers to maildir"); ++- return (sent(BOUNCE_FLAGS(state.request), ++- SENT_ATTR(state.msg_attr))); +++ dsb_simple(why, "2.0.0", "delivers to maildir"); +++ return (sent(BOUNCE_FLAGS(state.request), SENT_ATTR(state.msg_attr))); ++ } ++ ++ /* ++@@ -109,17 +486,91 @@ ++ * attribute to reflect the final recipient. ++ */ ++ if (vstream_fseek(state.msg_attr.fp, state.msg_attr.offset, SEEK_SET) < 0) ++- msg_fatal("seek message file %s: %m", VSTREAM_PATH(state.msg_attr.fp)); +++ msg_fatal("seek message file %s: %m", VSTREAM_PATH(state.msg_attr.fp)); ++ state.msg_attr.delivered = state.msg_attr.rcpt.address; ++ mail_copy_status = MAIL_COPY_STAT_WRITE; ++ buf = vstring_alloc(100); ++ ++- copy_flags = MAIL_COPY_TOFILE | MAIL_COPY_RETURN_PATH ++- | MAIL_COPY_DELIVERED | MAIL_COPY_ORIG_RCPT; +++ copy_flags = MAIL_COPY_TOFILE | MAIL_COPY_RETURN_PATH | MAIL_COPY_DELIVERED | MAIL_COPY_ORIG_RCPT; ++ ++- newdir = concatenate(usr_attr.mailbox, "new/", (char *) 0); ++- tmpdir = concatenate(usr_attr.mailbox, "tmp/", (char *) 0); ++- curdir = concatenate(usr_attr.mailbox, "cur/", (char *) 0); +++ /* +++ * Concatenate the maildir suffix (if set). +++ */ +++ if (*var_virt_maildir_suffix == 0) { +++ newdir = concatenate(usr_attr.mailbox, "new/", (char *) 0); +++ tmpdir = concatenate(usr_attr.mailbox, "tmp/", (char *) 0); +++ curdir = concatenate(usr_attr.mailbox, "cur/", (char *) 0); +++ } +++ else { +++ newdir = concatenate(usr_attr.mailbox, var_virt_maildir_suffix, (char *) 0); +++ tmpdir = concatenate(usr_attr.mailbox, var_virt_maildir_suffix, (char *) 0); +++ curdir = concatenate(usr_attr.mailbox, var_virt_maildir_suffix, (char *) 0); +++ newdir = concatenate(newdir, "new/", (char *) 0); +++ tmpdir = concatenate(tmpdir, "tmp/", (char *) 0); +++ curdir = concatenate(curdir, "cur/", (char *) 0); +++ } +++ +++ /* +++ * Look up the virtual maildir limit size for this user. +++ * Fall back to virtual_mailbox_limit in case lookup failed. +++ * If virtual maildir limit size is negative, fall back to virtual_mailbox_limit. +++ * If it's 0, set the mailbox limit to 0, which means unlimited. +++ * If it's more than 0 (positive int), check if the value is smaller than the maximum message size, +++ * if it is and the virtual maildir limit can't be overridden, fall back to virtual_mailbox_limit and +++ * warn the user, else use the value directly as the maildir limit. +++ */ +++ if (*var_virt_mailbox_limit_maps != 0 && (limit_res = mail_addr_find(virtual_mailbox_limit_maps, state.msg_attr.user, (char **) NULL)) != 0) { +++ n = atol(limit_res); +++ if (n > 0) { +++ if ((n < var_message_limit) && (!var_virt_mailbox_limit_override)) { +++ n = var_virt_mailbox_limit; +++ +++ msg_warn("%s: recipient %s - virtual maildir limit is " +++ "smaller than %s in %s - falling back to %s", +++ myname, +++ state.msg_attr.user, +++ VAR_MESSAGE_LIMIT, +++ virtual_mailbox_limit_maps->title, +++ VAR_VIRT_MAILBOX_LIMIT); +++ } +++ else { +++ if (msg_verbose) +++ msg_info("%s: set virtual maildir limit size for %s to %ld", +++ myname, usr_attr.mailbox, n); +++ } +++ } +++ else if (n == 0) { +++ if (msg_verbose) +++ msg_info("%s: set virtual maildir limit size for %s to %ld", +++ myname, usr_attr.mailbox, n); +++ } +++ else { +++ /* Invalid limit size (negative). Use default virtual_mailbox_limit. */ +++ n = var_virt_mailbox_limit; +++ } +++ } +++ else { +++ /* There is no limit in the maps. Use default virtual_mailbox_limit. */ +++ n = var_virt_mailbox_limit; +++ } +++ +++ /* +++ * Check quota before delivering the mail. +++ */ +++ if (n != 0) { +++ set_eugid(usr_attr.uid, usr_attr.gid); +++ if (var_virt_mailbox_limit_inbox) { +++ /* Check Inbox only (new, cur and tmp dirs). */ +++ saved_size = check_dir_size(newdir, &saved_count); +++ saved_size += check_dir_size(curdir, &saved_count); +++ saved_size += check_dir_size(tmpdir, &saved_count); +++ } +++ else { +++ /* Check all boxes. */ +++ saved_size = check_dir_size(usr_attr.mailbox, &saved_count); +++ } +++ set_eugid(var_owner_uid, var_owner_gid); +++ } ++ ++ /* ++ * Create and write the file as the recipient, so that file quota work. ++@@ -174,46 +625,296 @@ ++ * [...] ++ */ ++ set_eugid(usr_attr.uid, usr_attr.gid); ++- vstring_sprintf(buf, "%lu.P%d.%s", ++- (unsigned long) starttime.tv_sec, var_pid, get_hostname()); +++ vstring_sprintf(buf, "%lu.P%d.%s", (unsigned long) starttime.tv_sec, var_pid, get_hostname()); ++ tmpfile = concatenate(tmpdir, STR(buf), (char *) 0); ++ newfile = 0; +++ bkpnewfile = 0; ++ if ((dst = vstream_fopen(tmpfile, O_WRONLY | O_CREAT | O_EXCL, 0600)) == 0 ++- && (errno != ENOENT ++- || make_dirs(tmpdir, 0700) < 0 ++- || (dst = vstream_fopen(tmpfile, O_WRONLY | O_CREAT | O_EXCL, 0600)) == 0)) { ++- dsb_simple(why, mbox_dsn(errno, "4.2.0"), ++- "create maildir file %s: %m", tmpfile); ++- } else if (fstat(vstream_fileno(dst), &st) < 0) { ++- ++- /* ++- * Coverity 200604: file descriptor leak in code that never executes. ++- * Code replaced by msg_fatal(), as it is not worthwhile to continue ++- * after an impossible error condition. ++- */ ++- msg_fatal("fstat %s: %m", tmpfile); ++- } else { ++- vstring_sprintf(buf, "%lu.V%lxI%lxM%lu.%s", ++- (unsigned long) starttime.tv_sec, ++- (unsigned long) st.st_dev, ++- (unsigned long) st.st_ino, ++- (unsigned long) starttime.tv_usec, ++- get_hostname()); ++- newfile = concatenate(newdir, STR(buf), (char *) 0); ++- if ((mail_copy_status = mail_copy(COPY_ATTR(state.msg_attr), ++- dst, copy_flags, "\n", ++- why)) == 0) { ++- if (sane_link(tmpfile, newfile) < 0 ++- && (errno != ENOENT ++- || (make_dirs(curdir, 0700), make_dirs(newdir, 0700)) < 0 ++- || sane_link(tmpfile, newfile) < 0)) { ++- dsb_simple(why, mbox_dsn(errno, "4.2.0"), ++- "create maildir file %s: %m", newfile); ++- mail_copy_status = MAIL_COPY_STAT_WRITE; ++- } ++- } ++- if (unlink(tmpfile) < 0) ++- msg_warn("remove %s: %m", tmpfile); +++ && (errno != ENOENT +++ || make_dirs(tmpdir, 0700) < 0 +++ || (dst = vstream_fopen(tmpfile, O_WRONLY | O_CREAT | O_EXCL, 0600)) == 0)) { +++ dsb_simple(why, mbox_dsn(errno, "4.2.0"), "create maildir file %s: %m", tmpfile); +++ } +++ else if (fstat(vstream_fileno(dst), &st) < 0) { +++ /* +++ * Coverity 200604: file descriptor leak in code that never executes. +++ * Code replaced by msg_fatal(), as it is not worthwhile to continue +++ * after an impossible error condition. +++ */ +++ msg_fatal("fstat %s: %m", tmpfile); +++ } +++ else { +++ vstring_sprintf(buf, "%lu.V%lxI%lxM%lu.%s", +++ (unsigned long) starttime.tv_sec, +++ (unsigned long) st.st_dev, +++ (unsigned long) st.st_ino, +++ (unsigned long) starttime.tv_usec, +++ get_hostname()); +++ newfile = concatenate(newdir, STR(buf), (char *) 0); +++ bkpnewfile = concatenate(STR(buf), (char *) 0); /* Will need it later, if we MOVE to other folders. */ +++ +++ if ((mail_copy_status = mail_copy(COPY_ATTR(state.msg_attr), dst, copy_flags, "\n", why)) == 0) { +++ /* +++ * Add a ",S=<sizeoffile>" to the newly written file according to the +++ * Maildir++ specifications: http://www.inter7.com/courierimap/README.maildirquota.html +++ * This needs a stat(2) of the tempfile and modification of the +++ * name of the file. +++ */ +++ if (stat(tmpfile, &mail_stat) == 0) { +++ if (n != 0) { +++ saved_size += (long) mail_stat.st_size; +++ saved_count++; +++ } +++ if (var_virt_maildir_extended) { +++ /* Append the size of the file to newfile. */ +++ vstring_sprintf(buf, ",S=%ld", (long) mail_stat.st_size); +++ newfile = concatenate(newfile, STR(buf), (char *) 0); +++ bkpnewfile = concatenate(bkpnewfile, STR(buf), (char *) 0); +++ } +++ } +++ +++ /* +++ * Now we have the maildir size in saved_size, compare it to the max +++ * quota value and eventually issue a message that we've overdrawn it. +++ */ +++ if (saved_size > n) { +++ mail_copy_status = MAIL_COPY_STAT_WRITE; +++ if (((long) mail_stat.st_size > n) || (var_virt_overquota_bounce)) +++ errno = EFBIG; +++ else +++ errno = EDQUOT; +++ } +++ else { +++ /* Maildirfilter code by rk@demiurg.net. */ +++ if (var_virt_maildir_filter) { +++ if (msg_verbose) +++ msg_info("%s: loading DICT filters", myname); +++ +++#define STREQUAL(x,y,l) (strncasecmp((x), (y), (l)) == 0 && (y)[l] == 0) +++#define MAIL_COPY_STAT_REJECT (1<<3) +++#define MAIL_COPY_STAT_DISCARD (1<<4) +++ +++ /* Read filters. */ +++ filtername = concatenate("regexp:", usr_attr.mailbox, "maildirfilter", (char *) 0); +++ sqlmtime = sql2file(strchr(filtername, '/'), state.msg_attr.user); +++ +++ /* Check if this filter is already registered as dictionary. */ +++ if (msg_verbose) +++ msg_info("%s: checking DICT filters for %s", myname, filtername); +++ +++ if ((FILTERS = dict_handle(filtername))) { +++ if (msg_verbose) +++ msg_info("%s: DICT filter found", myname); +++ +++ /* +++ * If we have mtime in our DICT structure, check it against sqlmtime +++ * and reload the filters if they differ. +++ */ +++ if (FILTERS->mtime > 0 && sqlmtime > 0 && FILTERS->mtime != sqlmtime) { +++ if (msg_verbose) +++ msg_info("%s: reloading DICT filters (dict_mtime=%ld != sql_mtime=%ld)", +++ myname, FILTERS->mtime, sqlmtime); +++ +++ dict_unregister(filtername); +++ FILTERS = dict_open(filtername, O_RDONLY, DICT_FLAG_LOCK); +++ dict_register(filtername, FILTERS); +++ FILTERS->mtime = sqlmtime; +++ } +++ } +++ else { +++ if (sqlmtime > 0) { +++ /* Registering filter as new dictionary. */ +++ if (msg_verbose) +++ msg_info("%s: loading DICT filters from %s (mtime=%ld)", +++ myname, filtername, sqlmtime); +++ +++ FILTERS = dict_open(filtername, O_RDONLY, DICT_FLAG_LOCK); +++ dict_register(filtername, FILTERS); +++ FILTERS->mtime = sqlmtime; +++ } +++ } +++ +++ if (FILTERS && (tmpfilter = vstream_fopen(tmpfile, O_RDONLY, 0))) { +++ fltstr = vstring_alloc(1024); +++ header = (char *) malloc(8192); /* !!!INSECURE!!! See 7168-hack below. */ +++ header[0] = 0; +++ vstring_get_nonl_bound(fltstr, tmpfilter, 1023); +++ header = concatenate(header, STR(fltstr), (char *) 0); +++ +++ while(!vstream_feof(tmpfilter) && fltstr->vbuf.data[0] && strlen(header) < 7168 ) { +++ vstring_get_nonl_bound(fltstr, tmpfilter, 1023); +++ /* Glue multiline headers, replacing leading TAB with space. */ +++ if (msg_verbose) +++ msg_info("%s: fltstr value: %s", myname, STR(fltstr)); +++ +++ if (fltstr->vbuf.data[0] == ' ' || fltstr->vbuf.data[0] == '\t' ) { +++ if (fltstr->vbuf.data[0] == '\t') +++ fltstr->vbuf.data[0] = ' '; +++ header = concatenate(header, STR(fltstr), (char *) 0); +++ } +++ else { +++ header = concatenate(header, "\n", STR(fltstr), (char *) 0); +++ } +++ } +++ +++ if (msg_verbose) +++ msg_info("%s: checking filter CMD for %s", myname, filtername); +++ +++ /* Check whole header part with regexp maps. */ +++ if ((value = dict_get(FILTERS, lowercase(header))) != 0) { +++ if (msg_verbose) +++ msg_info("%s: preparing filter CMD", myname); +++ +++ cmd_text = value + strcspn(value, " \t"); +++ cmd_len = cmd_text - value; +++ while (*cmd_text && ISSPACE(*cmd_text)) +++ cmd_text++; +++ +++ if (msg_verbose) +++ msg_info("%s: executing filter CMD", myname); +++ +++ if (STREQUAL(value, "REJECT", cmd_len)) { +++ if (msg_verbose) +++ msg_info("%s: executing filter CMD REJECT", myname); +++ +++ mail_copy_status = MAIL_COPY_STAT_REJECT; +++ vstring_sprintf(why->reason, "%s", cmd_text); +++ dsb_simple(why, "5.0.0", "User filter - REJECT"); +++ } +++ +++ if (STREQUAL(value, "DISCARD", cmd_len)) { +++ if (msg_verbose) +++ msg_info("%s: executing filter CMD DISCARD", myname); +++ +++ mail_copy_status = MAIL_COPY_STAT_DISCARD; +++ vstring_sprintf(why->reason, "%s", cmd_text); +++ dsb_simple(why, "5.0.0", "User filter - DISCARD"); +++ } +++ +++ if (var_virt_maildir_extended) { +++ if (STREQUAL(value, "MOVE", cmd_len)) { +++ if (msg_verbose) +++ msg_info("%s: executing filter CMD MOVE", myname); +++ +++ strcut((char *) cmd_text, " "); +++ strcut((char *) cmd_text, "\t"); +++ strcut((char *) cmd_text, "/"); +++ strcut((char *) cmd_text, ".."); +++ +++ if (*var_virt_maildir_suffix == 0) { +++ newfile = concatenate(usr_attr.mailbox, (char *) 0); +++ } +++ else { +++ newfile = concatenate(usr_attr.mailbox, var_virt_maildir_suffix, (char *) 0); +++ } +++ +++ if (cmd_text[0] != '.') { +++ newfile = concatenate(newfile, ".", (char *) 0); +++ } +++ newdir = concatenate(newfile, cmd_text, "/", "new/", (char *) 0); +++ tmpdir = concatenate(newfile, cmd_text, "/", "tmp/", (char *) 0); +++ curdir = concatenate(newfile, cmd_text, "/", "cur/", (char *) 0); +++ mdffilename = concatenate(newfile, cmd_text, "/", "maildirfolder", (char *) 0); +++ newfile = concatenate(newfile, cmd_text, "/", "new/", bkpnewfile, (char *) 0); +++ } +++ } +++ +++ if (STREQUAL(value, "LOG", cmd_len) || STREQUAL(value, "WARN", cmd_len)) { +++ msg_warn("%s: header check warning: %s", myname, cmd_text); +++ } +++ +++ if (STREQUAL(value, "INFO", cmd_len)) { +++ msg_info("%s: header check info: %s", myname, cmd_text); +++ } +++ +++ if (msg_verbose) +++ msg_info("%s: exiting filter CMD", myname); +++ } /* End-Of-Check */ +++ +++ myfree(header); +++ vstring_free(fltstr); +++ vstream_fclose(tmpfilter); +++ } +++ +++ myfree(filtername); +++ } /* End-Of-Maildirfilter */ +++ +++ /* Deliver to curdir. */ +++ if (mail_copy_status == 0) { +++ if (sane_link(tmpfile, newfile) < 0 +++ && (errno != ENOENT +++ || (make_dirs(curdir, 0700), make_dirs(newdir, 0700), make_dirs(tmpdir, 0700)) < 0 +++ || sane_link(tmpfile, newfile) < 0)) { +++ dsb_simple(why, mbox_dsn(errno, "4.2.0"), "create maildir file %s: %m", newfile); +++ mail_copy_status = MAIL_COPY_STAT_WRITE; +++ } +++ +++ if (var_virt_maildir_extended) { +++ time(&tm); +++ +++ if (*var_virt_maildir_suffix == 0) { +++ sizefilename = concatenate(usr_attr.mailbox, "maildirsize", (char *) 0); +++ } +++ else { +++ sizefilename = concatenate(usr_attr.mailbox, var_virt_maildir_suffix, (char *) 0); +++ sizefilename = concatenate(sizefilename, "maildirsize", (char *) 0); +++ } +++ +++ /* Check if the quota in the file is the same as the current one, if not, delete the file. */ +++ sizefile = vstream_fopen(sizefilename, O_RDONLY, 0); +++ if (sizefile) { +++ filequota = vstring_alloc(128); +++ vstring_get_null_bound(filequota, sizefile, 127); +++ vstream_fclose(sizefile); +++ if (atol(vstring_export(filequota)) != n) +++ unlink(sizefilename); +++ } +++ +++ /* Open maildirsize file to append this transaction. */ +++ sizefile = vstream_fopen(sizefilename, O_WRONLY | O_APPEND, 0640); +++ +++ /* If the open fails (maildirsize doesn't exist), or it's too large, or too old, overwrite it. */ +++ if(!sizefile || (stat(sizefilename, &sizefile_stat) < 0) || (sizefile_stat.st_size > SIZEFILE_MAX) || (sizefile_stat.st_mtime + 15*60 < tm)) { +++ /* If the file exists, sizefile has been opened above, so close it first. */ +++ if (sizefile) { +++ vstream_fclose(sizefile); +++ sizefile = vstream_fopen(sizefilename, O_WRONLY | O_TRUNC, 0640); +++ } +++ else { +++ sizefile = vstream_fopen(sizefilename, O_WRONLY | O_CREAT, 0640); +++ } +++ +++ /* If the creation worked, write to the file, otherwise just give up. */ +++ if (sizefile) { +++ vstream_fprintf(sizefile, "%ldS\n%ld %ld\n", n, saved_size, saved_count); +++ vstream_fclose(sizefile); +++ } +++ } +++ else { +++ /* We opened maildirsize, so let's just append this transaction and close it. */ +++ vstream_fprintf(sizefile, "%ld 1\n", (long) mail_stat.st_size); +++ vstream_fclose(sizefile); +++ } +++ +++ /* +++ * 1) mdffilename != 0, so the maildirfilter code went through the MOVE to subfolder rule. +++ * 2) stat() failed, maybe the file does not exist? Try to create it. +++ */ +++ if (mdffilename && (stat(mdffilename, &mdffile_stat) < 0)) { +++ mdffile = vstream_fopen(mdffilename, O_WRONLY | O_CREAT, 0600); +++ if (mdffile) { +++ vstream_fclose(mdffile); +++ } +++ else { +++ msg_warn("Cannot create maildirfolder file '%s': %s", mdffilename, strerror(errno)); +++ } +++ } +++ } +++ } +++ } +++ } +++ if (unlink(tmpfile) < 0) +++ msg_warn("remove %s: %m", tmpfile); ++ } ++ set_eugid(var_owner_uid, var_owner_gid); ++ ++@@ -223,31 +924,64 @@ ++ * location possibly under user control. ++ */ ++ if (mail_copy_status & MAIL_COPY_STAT_CORRUPT) { ++- deliver_status = DEL_STAT_DEFER; ++- } else if (mail_copy_status != 0) { ++- if (errno == EACCES) { ++- msg_warn("maildir access problem for UID/GID=%lu/%lu: %s", ++- (long) usr_attr.uid, (long) usr_attr.gid, ++- STR(why->reason)); ++- msg_warn("perhaps you need to create the maildirs in advance"); ++- } ++- vstring_sprintf_prepend(why->reason, "maildir delivery failed: "); ++- deliver_status = ++- (STR(why->status)[0] == '4' ? ++- defer_append : bounce_append) ++- (BOUNCE_FLAGS(state.request), ++- BOUNCE_ATTR(state.msg_attr)); ++- } else { ++- dsb_simple(why, "2.0.0", "delivered to maildir"); ++- deliver_status = sent(BOUNCE_FLAGS(state.request), ++- SENT_ATTR(state.msg_attr)); +++ deliver_status = DEL_STAT_DEFER; +++ } +++ else if (mail_copy_status != 0) { +++ if (errno == EACCES) { +++ msg_warn("maildir access problem for UID/GID=%lu/%lu: %s", +++ (long) usr_attr.uid, (long) usr_attr.gid, STR(why->reason)); +++ msg_warn("perhaps you need to create the maildirs in advance"); +++ } +++ +++ /* Support per-recipient bounce messages. */ +++ const char *limit_message; +++ int errnored = errno; /* Seems like mail_addr_find resets errno ... */ +++ +++ if (*var_virt_maildir_limit_message_maps != 0 && (limit_message = mail_addr_find(virtual_maildir_limit_message_maps, state.msg_attr.user, (char **) NULL)) != 0) { +++ errno = errnored; +++ if (errno == EFBIG) { +++ dsb_simple(why, "5.2.3", limit_message); +++ } +++ if (errno == EDQUOT) { +++ dsb_simple(why, "4.2.2", limit_message); +++ } +++ } +++ else { +++ errno = errnored; +++ if (errno == EFBIG) { +++ dsb_simple(why, "5.2.3", var_virt_maildir_limit_message); +++ } +++ if (errno == EDQUOT) { +++ dsb_simple(why, "4.2.2", var_virt_maildir_limit_message); +++ } +++ } +++ +++ vstring_sprintf_prepend(why->reason, "maildir delivery failed: "); +++ deliver_status = +++ (STR(why->status)[0] == '4' ? defer_append : bounce_append) +++ (BOUNCE_FLAGS(state.request), BOUNCE_ATTR(state.msg_attr)); ++ } +++ else { +++ dsb_simple(why, "2.0.0", "delivered to maildir"); +++ deliver_status = sent(BOUNCE_FLAGS(state.request), SENT_ATTR(state.msg_attr)); +++ } +++ ++ vstring_free(buf); +++ ++ myfree(newdir); ++ myfree(tmpdir); ++ myfree(curdir); +++ +++ if (sizefilename) +++ myfree(sizefilename); +++ if (mdffilename) +++ myfree(mdffilename); +++ ++ myfree(tmpfile); ++ if (newfile) ++- myfree(newfile); +++ myfree(newfile); +++ if (bkpnewfile) +++ myfree(bkpnewfile); +++ ++ return (deliver_status); ++ } ++diff -Nru postfix-2.4.6/src/virtual/virtual.c postfix-2.4.6-vda-ng/src/virtual/virtual.c ++--- postfix-2.4.6/src/virtual/virtual.c 2007-03-27 02:07:43.000000000 +0200 +++++ postfix-2.4.6-vda-ng/src/virtual/virtual.c 2007-11-24 12:48:53.000000000 +0100 ++@@ -330,12 +330,28 @@ ++ int var_virt_mailbox_limit; ++ char *var_mail_spool_dir; /* XXX dependency fix */ ++ +++char *var_virt_mailbox_limit_maps; +++bool var_virt_mailbox_limit_inbox; +++bool var_virt_mailbox_limit_override; +++bool var_virt_maildir_extended; +++bool var_virt_overquota_bounce; +++char *var_virt_maildir_limit_message; +++char *var_virt_maildir_limit_message_maps; +++char *var_virt_maildir_suffix; +++bool var_virt_trash_count; +++char *var_virt_trash_name; +++bool var_virt_maildir_filter; +++char *var_virt_maildir_filter_maps; +++ ++ /* ++ * Mappings. ++ */ ++ MAPS *virtual_mailbox_maps; ++ MAPS *virtual_uid_maps; ++ MAPS *virtual_gid_maps; +++MAPS *virtual_mailbox_limit_maps; +++MAPS *virtual_maildir_limit_message_maps; +++MAPS *virtual_maildir_filter_maps; ++ ++ /* ++ * Bit masks. ++@@ -445,15 +461,24 @@ ++ */ ++ virtual_mailbox_maps = ++ maps_create(VAR_VIRT_MAILBOX_MAPS, var_virt_mailbox_maps, ++- DICT_FLAG_LOCK | DICT_FLAG_PARANOID); ++- +++ DICT_FLAG_LOCK); ++ virtual_uid_maps = ++ maps_create(VAR_VIRT_UID_MAPS, var_virt_uid_maps, ++- DICT_FLAG_LOCK | DICT_FLAG_PARANOID); ++- +++ DICT_FLAG_LOCK); ++ virtual_gid_maps = ++ maps_create(VAR_VIRT_GID_MAPS, var_virt_gid_maps, ++- DICT_FLAG_LOCK | DICT_FLAG_PARANOID); +++ DICT_FLAG_LOCK); +++ virtual_mailbox_limit_maps = +++ maps_create(VAR_VIRT_MAILBOX_LIMIT_MAPS, var_virt_mailbox_limit_maps, +++ DICT_FLAG_LOCK); +++ +++ virtual_maildir_limit_message_maps = +++ maps_create(VAR_VIRT_MAILDIR_LIMIT_MESSAGE_MAPS, var_virt_maildir_limit_message_maps, +++ DICT_FLAG_LOCK); +++ +++ virtual_maildir_filter_maps = +++ maps_create(VAR_VIRT_MAILDIR_FILTER_MAPS, var_virt_maildir_filter_maps, +++ DICT_FLAG_LOCK); ++ ++ virtual_mbox_lock_mask = mbox_lock_mask(var_virt_mailbox_lock); ++ } ++@@ -495,16 +520,33 @@ ++ VAR_VIRT_MAILBOX_LIMIT, DEF_VIRT_MAILBOX_LIMIT, &var_virt_mailbox_limit, 0, 0, ++ 0, ++ }; ++- static CONFIG_STR_TABLE str_table[] = { ++- VAR_MAIL_SPOOL_DIR, DEF_MAIL_SPOOL_DIR, &var_mail_spool_dir, 0, 0, ++- VAR_VIRT_MAILBOX_MAPS, DEF_VIRT_MAILBOX_MAPS, &var_virt_mailbox_maps, 0, 0, ++- VAR_VIRT_UID_MAPS, DEF_VIRT_UID_MAPS, &var_virt_uid_maps, 0, 0, ++- VAR_VIRT_GID_MAPS, DEF_VIRT_GID_MAPS, &var_virt_gid_maps, 0, 0, ++- VAR_VIRT_MAILBOX_BASE, DEF_VIRT_MAILBOX_BASE, &var_virt_mailbox_base, 1, 0, ++- VAR_VIRT_MAILBOX_LOCK, DEF_VIRT_MAILBOX_LOCK, &var_virt_mailbox_lock, 1, 0, ++- 0, +++ +++ static CONFIG_BOOL_TABLE bool_table[] = { +++ VAR_VIRT_MAILBOX_LIMIT_INBOX, DEF_VIRT_MAILBOX_LIMIT_INBOX, &var_virt_mailbox_limit_inbox, +++ VAR_VIRT_MAILBOX_LIMIT_OVERRIDE, DEF_VIRT_MAILBOX_LIMIT_OVERRIDE, &var_virt_mailbox_limit_override, +++ VAR_VIRT_MAILDIR_EXTENDED, DEF_VIRT_MAILDIR_EXTENDED, &var_virt_maildir_extended, +++ VAR_VIRT_OVERQUOTA_BOUNCE, DEF_VIRT_OVERQUOTA_BOUNCE, &var_virt_overquota_bounce, +++ VAR_VIRT_TRASH_COUNT, DEF_VIRT_TRASH_COUNT, &var_virt_trash_count, +++ VAR_VIRT_MAILDIR_FILTER, DEF_VIRT_MAILDIR_FILTER, &var_virt_maildir_filter, +++ 0, ++ }; ++ +++ static CONFIG_STR_TABLE str_table[] = { +++ VAR_MAIL_SPOOL_DIR, DEF_MAIL_SPOOL_DIR, &var_mail_spool_dir, 0, 0, +++ VAR_VIRT_MAILBOX_MAPS, DEF_VIRT_MAILBOX_MAPS, &var_virt_mailbox_maps, 0, 0, +++ VAR_VIRT_UID_MAPS, DEF_VIRT_UID_MAPS, &var_virt_uid_maps, 0, 0, +++ VAR_VIRT_GID_MAPS, DEF_VIRT_GID_MAPS, &var_virt_gid_maps, 0, 0, +++ VAR_VIRT_MAILBOX_LIMIT_MAPS, DEF_VIRT_MAILBOX_LIMIT_MAPS, &var_virt_mailbox_limit_maps, 0, 0, +++ VAR_VIRT_MAILBOX_BASE, DEF_VIRT_MAILBOX_BASE, &var_virt_mailbox_base, 1, 0, +++ VAR_VIRT_MAILBOX_LOCK, DEF_VIRT_MAILBOX_LOCK, &var_virt_mailbox_lock, 1, 0, +++ VAR_VIRT_MAILDIR_LIMIT_MESSAGE, DEF_VIRT_MAILDIR_LIMIT_MESSAGE, &var_virt_maildir_limit_message, 1, 0, +++ VAR_VIRT_MAILDIR_LIMIT_MESSAGE_MAPS, DEF_VIRT_MAILDIR_LIMIT_MESSAGE_MAPS, &var_virt_maildir_limit_message_maps, 0, 0, +++ VAR_VIRT_MAILDIR_SUFFIX, DEF_VIRT_MAILDIR_SUFFIX, &var_virt_maildir_suffix, 0, 0, +++ VAR_VIRT_TRASH_NAME, DEF_VIRT_TRASH_NAME, &var_virt_trash_name, 0, 0, +++ VAR_VIRT_MAILDIR_FILTER_MAPS, DEF_VIRT_MAILDIR_FILTER_MAPS, &var_virt_maildir_filter_maps, 0, 0, +++ 0, +++ }; +++ ++ /* ++ * Fingerprint executables and core dumps. ++ */ ++@@ -516,6 +558,7 @@ ++ MAIL_SERVER_PRE_INIT, pre_init, ++ MAIL_SERVER_POST_INIT, post_init, ++ MAIL_SERVER_PRE_ACCEPT, pre_accept, +++ MAIL_SERVER_BOOL_TABLE, bool_table, ++ MAIL_SERVER_PRIVILEGED, ++ 0); ++ } ++diff -Nru postfix-2.4.6/src/virtual/virtual.h postfix-2.4.6-vda-ng/src/virtual/virtual.h ++--- postfix-2.4.6/src/virtual/virtual.h 2006-01-08 00:59:47.000000000 +0100 +++++ postfix-2.4.6-vda-ng/src/virtual/virtual.h 2007-11-24 12:48:53.000000000 +0100 ++@@ -34,6 +34,9 @@ ++ extern MAPS *virtual_mailbox_maps; ++ extern MAPS *virtual_uid_maps; ++ extern MAPS *virtual_gid_maps; +++extern MAPS *virtual_mailbox_limit_maps; +++extern MAPS *virtual_maildir_limit_message_maps; +++extern MAPS *virtual_maildir_filter_maps; ++ ++ /* ++ * User attributes: these control the privileges for delivery to external +diff -Nru postfix-2.5.1/src/global/mail_params.h postfix-2.5.1-vda-ng/src/global/mail_params.h +--- postfix-2.5.1/src/global/mail_params.h 2008-01-24 02:10:19.000000000 +0100 ++++ postfix-2.5.1-vda-ng/src/global/mail_params.h 2008-03-15 15:06:00.095731675 +0100 +@@ -2167,6 +2167,54 @@ #define DEF_VIRT_GID_MAPS "" extern char *var_virt_gid_maps; @@ -157,9 +1600,9 @@ diff -Nru postfix-2.4.6/src/global/mail_params.h postfix-2.4.6-vda-ng/src/global #define VAR_VIRT_MINUID "virtual_minimum_uid" #define DEF_VIRT_MINUID 100 extern int var_virt_minimum_uid; -diff -Nru postfix-2.4.6/src/util/file_limit.c postfix-2.4.6-vda-ng/src/util/file_limit.c ---- postfix-2.4.6/src/util/file_limit.c 2003-10-22 20:48:36.000000000 +0200 -+++ postfix-2.4.6-vda-ng/src/util/file_limit.c 2007-11-24 12:48:53.000000000 +0100 +diff -Nru postfix-2.5.1/src/util/file_limit.c postfix-2.5.1-vda-ng/src/util/file_limit.c +--- postfix-2.5.1/src/util/file_limit.c 2003-10-22 20:48:36.000000000 +0200 ++++ postfix-2.5.1-vda-ng/src/util/file_limit.c 2008-03-15 15:06:00.539717108 +0100 @@ -85,7 +85,11 @@ #else struct rlimit rlim; @@ -173,9 +1616,9 @@ diff -Nru postfix-2.4.6/src/util/file_limit.c postfix-2.4.6-vda-ng/src/util/file if (setrlimit(RLIMIT_FSIZE, &rlim) < 0) msg_fatal("setrlimit: %m"); #ifdef SIGXFSZ -diff -Nru postfix-2.4.6/src/virtual/mailbox.c postfix-2.4.6-vda-ng/src/virtual/mailbox.c ---- postfix-2.4.6/src/virtual/mailbox.c 2006-06-26 14:59:19.000000000 +0200 -+++ postfix-2.4.6-vda-ng/src/virtual/mailbox.c 2007-11-26 12:30:21.000000000 +0100 +diff -Nru postfix-2.5.1/src/virtual/mailbox.c postfix-2.5.1-vda-ng/src/virtual/mailbox.c +--- postfix-2.5.1/src/virtual/mailbox.c 2006-06-26 14:59:19.000000000 +0200 ++++ postfix-2.5.1-vda-ng/src/virtual/mailbox.c 2008-03-15 15:06:00.951703589 +0100 @@ -70,6 +70,70 @@ #define YES 1 #define NO 0 @@ -355,9 +1798,9 @@ diff -Nru postfix-2.4.6/src/virtual/mailbox.c postfix-2.4.6-vda-ng/src/virtual/m /* * Cleanup. -diff -Nru postfix-2.4.6/src/virtual/maildir.c postfix-2.4.6-vda-ng/src/virtual/maildir.c ---- postfix-2.4.6/src/virtual/maildir.c 2006-06-26 14:59:19.000000000 +0200 -+++ postfix-2.4.6-vda-ng/src/virtual/maildir.c 2007-11-24 13:20:57.000000000 +0100 +diff -Nru postfix-2.5.1/src/virtual/maildir.c postfix-2.5.1-vda-ng/src/virtual/maildir.c +--- postfix-2.5.1/src/virtual/maildir.c 2006-06-26 14:59:19.000000000 +0200 ++++ postfix-2.5.1-vda-ng/src/virtual/maildir.c 2008-03-15 15:06:01.303692043 +0100 @@ -63,28 +63,406 @@ #include <mbox_open.h> #include <dsn_util.h> @@ -1312,9 +2755,9 @@ diff -Nru postfix-2.4.6/src/virtual/maildir.c postfix-2.4.6-vda-ng/src/virtual/m + return (deliver_status); } -diff -Nru postfix-2.4.6/src/virtual/virtual.c postfix-2.4.6-vda-ng/src/virtual/virtual.c ---- postfix-2.4.6/src/virtual/virtual.c 2007-03-27 02:07:43.000000000 +0200 -+++ postfix-2.4.6-vda-ng/src/virtual/virtual.c 2007-11-24 12:48:53.000000000 +0100 +diff -Nru postfix-2.5.1/src/virtual/virtual.c postfix-2.5.1-vda-ng/src/virtual/virtual.c +--- postfix-2.5.1/src/virtual/virtual.c 2008-01-08 21:35:08.000000000 +0100 ++++ postfix-2.5.1-vda-ng/src/virtual/virtual.c 2008-03-15 15:12:30.906943990 +0100 @@ -330,12 +330,28 @@ int var_virt_mailbox_limit; char *var_mail_spool_dir; /* XXX dependency fix */ @@ -1374,11 +2817,16 @@ diff -Nru postfix-2.4.6/src/virtual/virtual.c postfix-2.4.6-vda-ng/src/virtual/v virtual_mbox_lock_mask = mbox_lock_mask(var_virt_mailbox_lock); } -@@ -495,16 +520,33 @@ - VAR_VIRT_MAILBOX_LIMIT, DEF_VIRT_MAILBOX_LIMIT, &var_virt_mailbox_limit, 0, 0, - 0, - }; -- static CONFIG_STR_TABLE str_table[] = { +@@ -490,20 +515,37 @@ + + int main(int argc, char **argv) + { +- static const CONFIG_INT_TABLE int_table[] = { +- VAR_VIRT_MINUID, DEF_VIRT_MINUID, &var_virt_minimum_uid, 1, 0, +- VAR_VIRT_MAILBOX_LIMIT, DEF_VIRT_MAILBOX_LIMIT, &var_virt_mailbox_limit, 0, 0, +- 0, +- }; +- static const CONFIG_STR_TABLE str_table[] = { - VAR_MAIL_SPOOL_DIR, DEF_MAIL_SPOOL_DIR, &var_mail_spool_dir, 0, 0, - VAR_VIRT_MAILBOX_MAPS, DEF_VIRT_MAILBOX_MAPS, &var_virt_mailbox_maps, 0, 0, - VAR_VIRT_UID_MAPS, DEF_VIRT_UID_MAPS, &var_virt_uid_maps, 0, 0, @@ -1386,47 +2834,577 @@ diff -Nru postfix-2.4.6/src/virtual/virtual.c postfix-2.4.6-vda-ng/src/virtual/v - VAR_VIRT_MAILBOX_BASE, DEF_VIRT_MAILBOX_BASE, &var_virt_mailbox_base, 1, 0, - VAR_VIRT_MAILBOX_LOCK, DEF_VIRT_MAILBOX_LOCK, &var_virt_mailbox_lock, 1, 0, - 0, +- }; ++ static const CONFIG_INT_TABLE int_table[] = { ++ VAR_VIRT_MINUID, DEF_VIRT_MINUID, &var_virt_minimum_uid, 1, 0, ++ VAR_VIRT_MAILBOX_LIMIT, DEF_VIRT_MAILBOX_LIMIT, &var_virt_mailbox_limit, 0, 0, ++ 0, ++ }; + -+ static CONFIG_BOOL_TABLE bool_table[] = { -+ VAR_VIRT_MAILBOX_LIMIT_INBOX, DEF_VIRT_MAILBOX_LIMIT_INBOX, &var_virt_mailbox_limit_inbox, -+ VAR_VIRT_MAILBOX_LIMIT_OVERRIDE, DEF_VIRT_MAILBOX_LIMIT_OVERRIDE, &var_virt_mailbox_limit_override, -+ VAR_VIRT_MAILDIR_EXTENDED, DEF_VIRT_MAILDIR_EXTENDED, &var_virt_maildir_extended, -+ VAR_VIRT_OVERQUOTA_BOUNCE, DEF_VIRT_OVERQUOTA_BOUNCE, &var_virt_overquota_bounce, -+ VAR_VIRT_TRASH_COUNT, DEF_VIRT_TRASH_COUNT, &var_virt_trash_count, -+ VAR_VIRT_MAILDIR_FILTER, DEF_VIRT_MAILDIR_FILTER, &var_virt_maildir_filter, -+ 0, - }; - -+ static CONFIG_STR_TABLE str_table[] = { -+ VAR_MAIL_SPOOL_DIR, DEF_MAIL_SPOOL_DIR, &var_mail_spool_dir, 0, 0, -+ VAR_VIRT_MAILBOX_MAPS, DEF_VIRT_MAILBOX_MAPS, &var_virt_mailbox_maps, 0, 0, -+ VAR_VIRT_UID_MAPS, DEF_VIRT_UID_MAPS, &var_virt_uid_maps, 0, 0, -+ VAR_VIRT_GID_MAPS, DEF_VIRT_GID_MAPS, &var_virt_gid_maps, 0, 0, -+ VAR_VIRT_MAILBOX_LIMIT_MAPS, DEF_VIRT_MAILBOX_LIMIT_MAPS, &var_virt_mailbox_limit_maps, 0, 0, -+ VAR_VIRT_MAILBOX_BASE, DEF_VIRT_MAILBOX_BASE, &var_virt_mailbox_base, 1, 0, -+ VAR_VIRT_MAILBOX_LOCK, DEF_VIRT_MAILBOX_LOCK, &var_virt_mailbox_lock, 1, 0, -+ VAR_VIRT_MAILDIR_LIMIT_MESSAGE, DEF_VIRT_MAILDIR_LIMIT_MESSAGE, &var_virt_maildir_limit_message, 1, 0, -+ VAR_VIRT_MAILDIR_LIMIT_MESSAGE_MAPS, DEF_VIRT_MAILDIR_LIMIT_MESSAGE_MAPS, &var_virt_maildir_limit_message_maps, 0, 0, -+ VAR_VIRT_MAILDIR_SUFFIX, DEF_VIRT_MAILDIR_SUFFIX, &var_virt_maildir_suffix, 0, 0, -+ VAR_VIRT_TRASH_NAME, DEF_VIRT_TRASH_NAME, &var_virt_trash_name, 0, 0, -+ VAR_VIRT_MAILDIR_FILTER_MAPS, DEF_VIRT_MAILDIR_FILTER_MAPS, &var_virt_maildir_filter_maps, 0, 0, -+ 0, ++ static const CONFIG_BOOL_TABLE bool_table[] = { ++ VAR_VIRT_MAILBOX_LIMIT_INBOX, DEF_VIRT_MAILBOX_LIMIT_INBOX, &var_virt_mailbox_limit_inbox, ++ VAR_VIRT_MAILBOX_LIMIT_OVERRIDE, DEF_VIRT_MAILBOX_LIMIT_OVERRIDE, &var_virt_mailbox_limit_override, ++ VAR_VIRT_MAILDIR_EXTENDED, DEF_VIRT_MAILDIR_EXTENDED, &var_virt_maildir_extended, ++ VAR_VIRT_OVERQUOTA_BOUNCE, DEF_VIRT_OVERQUOTA_BOUNCE, &var_virt_overquota_bounce, ++ VAR_VIRT_TRASH_COUNT, DEF_VIRT_TRASH_COUNT, &var_virt_trash_count, ++ VAR_VIRT_MAILDIR_FILTER, DEF_VIRT_MAILDIR_FILTER, &var_virt_maildir_filter, ++ 0, + }; + ++ static const CONFIG_STR_TABLE str_table[] = { ++ VAR_MAIL_SPOOL_DIR, DEF_MAIL_SPOOL_DIR, &var_mail_spool_dir, 0, 0, ++ VAR_VIRT_MAILBOX_MAPS, DEF_VIRT_MAILBOX_MAPS, &var_virt_mailbox_maps, 0, 0, ++ VAR_VIRT_UID_MAPS, DEF_VIRT_UID_MAPS, &var_virt_uid_maps, 0, 0, ++ VAR_VIRT_GID_MAPS, DEF_VIRT_GID_MAPS, &var_virt_gid_maps, 0, 0, ++ VAR_VIRT_MAILBOX_LIMIT_MAPS, DEF_VIRT_MAILBOX_LIMIT_MAPS, &var_virt_mailbox_limit_maps, 0, 0, ++ VAR_VIRT_MAILBOX_BASE, DEF_VIRT_MAILBOX_BASE, &var_virt_mailbox_base, 1, 0, ++ VAR_VIRT_MAILBOX_LOCK, DEF_VIRT_MAILBOX_LOCK, &var_virt_mailbox_lock, 1, 0, ++ VAR_VIRT_MAILDIR_LIMIT_MESSAGE, DEF_VIRT_MAILDIR_LIMIT_MESSAGE, &var_virt_maildir_limit_message, 1, 0, ++ VAR_VIRT_MAILDIR_LIMIT_MESSAGE_MAPS, DEF_VIRT_MAILDIR_LIMIT_MESSAGE_MAPS, &var_virt_maildir_limit_message_maps, 0, 0, ++ VAR_VIRT_MAILDIR_SUFFIX, DEF_VIRT_MAILDIR_SUFFIX, &var_virt_maildir_suffix, 0, 0, ++ VAR_VIRT_TRASH_NAME, DEF_VIRT_TRASH_NAME, &var_virt_trash_name, 0, 0, ++ VAR_VIRT_MAILDIR_FILTER_MAPS, DEF_VIRT_MAILDIR_FILTER_MAPS, &var_virt_maildir_filter_maps, 0, 0, ++ 0, ++ }; + /* * Fingerprint executables and core dumps. - */ @@ -516,6 +558,7 @@ MAIL_SERVER_PRE_INIT, pre_init, MAIL_SERVER_POST_INIT, post_init, MAIL_SERVER_PRE_ACCEPT, pre_accept, -+ MAIL_SERVER_BOOL_TABLE, bool_table, ++ MAIL_SERVER_BOOL_TABLE, bool_table, MAIL_SERVER_PRIVILEGED, 0); } -diff -Nru postfix-2.4.6/src/virtual/virtual.h postfix-2.4.6-vda-ng/src/virtual/virtual.h ---- postfix-2.4.6/src/virtual/virtual.h 2006-01-08 00:59:47.000000000 +0100 -+++ postfix-2.4.6-vda-ng/src/virtual/virtual.h 2007-11-24 12:48:53.000000000 +0100 +diff -Nru postfix-2.5.1/src/virtual/virtual.c.orig postfix-2.5.1-vda-ng/src/virtual/virtual.c.orig +--- postfix-2.5.1/src/virtual/virtual.c.orig 1970-01-01 01:00:00.000000000 +0100 ++++ postfix-2.5.1-vda-ng/src/virtual/virtual.c.orig 2008-03-15 15:05:24.128912042 +0100 +@@ -0,0 +1,521 @@ ++/*++ ++/* NAME ++/* virtual 8 ++/* SUMMARY ++/* Postfix virtual domain mail delivery agent ++/* SYNOPSIS ++/* \fBvirtual\fR [generic Postfix daemon options] ++/* DESCRIPTION ++/* The \fBvirtual\fR(8) delivery agent is designed for virtual mail ++/* hosting services. Originally based on the Postfix \fBlocal\fR(8) ++/* delivery ++/* agent, this agent looks up recipients with map lookups of their ++/* full recipient address, instead of using hard-coded unix password ++/* file lookups of the address local part only. ++/* ++/* This delivery agent only delivers mail. Other features such as ++/* mail forwarding, out-of-office notifications, etc., must be ++/* configured via virtual_alias maps or via similar lookup mechanisms. ++/* MAILBOX LOCATION ++/* .ad ++/* .fi ++/* The mailbox location is controlled by the \fBvirtual_mailbox_base\fR ++/* and \fBvirtual_mailbox_maps\fR configuration parameters (see below). ++/* The \fBvirtual_mailbox_maps\fR table is indexed by the recipient ++/* address as described under TABLE SEARCH ORDER below. ++/* ++/* The mailbox pathname is constructed as follows: ++/* ++/* .nf ++/* \fB$virtual_mailbox_base/$virtual_mailbox_maps(\fIrecipient\fB)\fR ++/* .fi ++/* ++/* where \fIrecipient\fR is the full recipient address. ++/* UNIX MAILBOX FORMAT ++/* .ad ++/* .fi ++/* When the mailbox location does not end in \fB/\fR, the message ++/* is delivered in UNIX mailbox format. This format stores multiple ++/* messages in one textfile. ++/* ++/* The \fBvirtual\fR(8) delivery agent prepends a "\fBFrom \fIsender ++/* time_stamp\fR" envelope header to each message, prepends a ++/* \fBDelivered-To:\fR message header with the envelope recipient ++/* address, ++/* prepends an \fBX-Original-To:\fR header with the recipient address as ++/* given to Postfix, ++/* prepends a \fBReturn-Path:\fR message header with the ++/* envelope sender address, prepends a \fB>\fR character to lines ++/* beginning with "\fBFrom \fR", and appends an empty line. ++/* ++/* The mailbox is locked for exclusive access while delivery is in ++/* progress. In case of problems, an attempt is made to truncate the ++/* mailbox to its original length. ++/* QMAIL MAILDIR FORMAT ++/* .ad ++/* .fi ++/* When the mailbox location ends in \fB/\fR, the message is delivered ++/* in qmail \fBmaildir\fR format. This format stores one message per file. ++/* ++/* The \fBvirtual\fR(8) delivery agent prepends a \fBDelivered-To:\fR ++/* message header with the final envelope recipient address, ++/* prepends an \fBX-Original-To:\fR header with the recipient address as ++/* given to Postfix, and prepends a ++/* \fBReturn-Path:\fR message header with the envelope sender address. ++/* ++/* By definition, \fBmaildir\fR format does not require application-level ++/* file locking during mail delivery or retrieval. ++/* MAILBOX OWNERSHIP ++/* .ad ++/* .fi ++/* Mailbox ownership is controlled by the \fBvirtual_uid_maps\fR ++/* and \fBvirtual_gid_maps\fR lookup tables, which are indexed ++/* with the full recipient address. Each table provides ++/* a string with the numerical user and group ID, respectively. ++/* ++/* The \fBvirtual_minimum_uid\fR parameter imposes a lower bound on ++/* numerical user ID values that may be specified in any ++/* \fBvirtual_uid_maps\fR. ++/* CASE FOLDING ++/* .ad ++/* .fi ++/* All delivery decisions are made using the full recipient ++/* address, folded to lower case. See also the next section ++/* for a few exceptions with optional address extensions. ++/* TABLE SEARCH ORDER ++/* .ad ++/* .fi ++/* Normally, a lookup table is specified as a text file that ++/* serves as input to the \fBpostmap\fR(1) command. The result, an ++/* indexed file in \fBdbm\fR or \fBdb\fR format, is used for fast ++/* searching by the mail system. ++/* ++/* The search order is as follows. The search stops ++/* upon the first successful lookup. ++/* .IP \(bu ++/* When the recipient has an optional address extension the ++/* \fIuser+extension@domain.tld\fR address is looked up first. ++/* .sp ++/* With Postfix versions before 2.1, the optional address extension ++/* is always ignored. ++/* .IP \(bu ++/* The \fIuser@domain.tld\fR address, without address extension, ++/* is looked up next. ++/* .IP \(bu ++/* Finally, the recipient \fI@domain\fR is looked up. ++/* .PP ++/* When the table is provided via other means such as NIS, LDAP ++/* or SQL, the same lookups are done as for ordinary indexed files. ++/* ++/* Alternatively, a table can be provided as a regular-expression ++/* map where patterns are given as regular expressions. In that case, ++/* only the full recipient address is given to the regular-expression ++/* map. ++/* SECURITY ++/* .ad ++/* .fi ++/* The \fBvirtual\fR(8) delivery agent is not security sensitive, provided ++/* that the lookup tables with recipient user/group ID information are ++/* adequately protected. This program is not designed to run chrooted. ++/* ++/* The \fBvirtual\fR(8) delivery agent disallows regular expression ++/* substitution of $1 etc. in regular expression lookup tables, ++/* because that would open a security hole. ++/* ++/* The \fBvirtual\fR(8) delivery agent will silently ignore requests ++/* to use the \fBproxymap\fR(8) server. Instead it will open the ++/* table directly. Before Postfix version 2.2, the virtual ++/* delivery agent will terminate with a fatal error. ++/* STANDARDS ++/* RFC 822 (ARPA Internet Text Messages) ++/* DIAGNOSTICS ++/* Mail bounces when the recipient has no mailbox or when the ++/* recipient is over disk quota. In all other cases, mail for ++/* an existing recipient is deferred and a warning is logged. ++/* ++/* Problems and transactions are logged to \fBsyslogd\fR(8). ++/* Corrupted message files are marked so that the queue ++/* manager can move them to the \fBcorrupt\fR queue afterwards. ++/* ++/* Depending on the setting of the \fBnotify_classes\fR parameter, ++/* the postmaster is notified of bounces and of other trouble. ++/* BUGS ++/* This delivery agent supports address extensions in email ++/* addresses and in lookup table keys, but does not propagate ++/* address extension information to the result of table lookup. ++/* ++/* Postfix should have lookup tables that can return multiple result ++/* attributes. In order to avoid the inconvenience of maintaining ++/* three tables, use an LDAP or MYSQL database. ++/* CONFIGURATION PARAMETERS ++/* .ad ++/* .fi ++/* Changes to \fBmain.cf\fR are picked up automatically, as ++/* \fBvirtual\fR(8) ++/* processes run for only a limited amount of time. Use the command ++/* "\fBpostfix reload\fR" to speed up a change. ++/* ++/* The text below provides only a parameter summary. See ++/* \fBpostconf\fR(5) for more details including examples. ++/* MAILBOX DELIVERY CONTROLS ++/* .ad ++/* .fi ++/* .IP "\fBvirtual_mailbox_base (empty)\fR" ++/* A prefix that the \fBvirtual\fR(8) delivery agent prepends to all pathname ++/* results from $virtual_mailbox_maps table lookups. ++/* .IP "\fBvirtual_mailbox_maps (empty)\fR" ++/* Optional lookup tables with all valid addresses in the domains that ++/* match $virtual_mailbox_domains. ++/* .IP "\fBvirtual_minimum_uid (100)\fR" ++/* The minimum user ID value that the \fBvirtual\fR(8) delivery agent accepts ++/* as a result from $virtual_uid_maps table lookup. ++/* .IP "\fBvirtual_uid_maps (empty)\fR" ++/* Lookup tables with the per-recipient user ID that the \fBvirtual\fR(8) ++/* delivery agent uses while writing to the recipient's mailbox. ++/* .IP "\fBvirtual_gid_maps (empty)\fR" ++/* Lookup tables with the per-recipient group ID for \fBvirtual\fR(8) mailbox ++/* delivery. ++/* .PP ++/* Available in Postfix version 2.0 and later: ++/* .IP "\fBvirtual_mailbox_domains ($virtual_mailbox_maps)\fR" ++/* Postfix is final destination for the specified list of domains; ++/* mail is delivered via the $virtual_transport mail delivery transport. ++/* .IP "\fBvirtual_transport (virtual)\fR" ++/* The default mail delivery transport and next-hop destination for ++/* final delivery to domains listed with $virtual_mailbox_domains. ++/* LOCKING CONTROLS ++/* .ad ++/* .fi ++/* .IP "\fBvirtual_mailbox_lock (see 'postconf -d' output)\fR" ++/* How to lock a UNIX-style \fBvirtual\fR(8) mailbox before attempting ++/* delivery. ++/* .IP "\fBdeliver_lock_attempts (20)\fR" ++/* The maximal number of attempts to acquire an exclusive lock on a ++/* mailbox file or \fBbounce\fR(8) logfile. ++/* .IP "\fBdeliver_lock_delay (1s)\fR" ++/* The time between attempts to acquire an exclusive lock on a mailbox ++/* file or \fBbounce\fR(8) logfile. ++/* .IP "\fBstale_lock_time (500s)\fR" ++/* The time after which a stale exclusive mailbox lockfile is removed. ++/* RESOURCE AND RATE CONTROLS ++/* .ad ++/* .fi ++/* .IP "\fBvirtual_destination_concurrency_limit ($default_destination_concurrency_limit)\fR" ++/* The maximal number of parallel deliveries to the same destination ++/* via the virtual message delivery transport. ++/* .IP "\fBvirtual_destination_recipient_limit ($default_destination_recipient_limit)\fR" ++/* The maximal number of recipients per delivery via the virtual ++/* message delivery transport. ++/* .IP "\fBvirtual_mailbox_limit (51200000)\fR" ++/* The maximal size in bytes of an individual mailbox or maildir file, ++/* or zero (no limit). ++/* MISCELLANEOUS CONTROLS ++/* .ad ++/* .fi ++/* .IP "\fBconfig_directory (see 'postconf -d' output)\fR" ++/* The default location of the Postfix main.cf and master.cf ++/* configuration files. ++/* .IP "\fBdaemon_timeout (18000s)\fR" ++/* How much time a Postfix daemon process may take to handle a ++/* request before it is terminated by a built-in watchdog timer. ++/* .IP "\fBdelay_logging_resolution_limit (2)\fR" ++/* The maximal number of digits after the decimal point when logging ++/* sub-second delay values. ++/* .IP "\fBipc_timeout (3600s)\fR" ++/* The time limit for sending or receiving information over an internal ++/* communication channel. ++/* .IP "\fBmax_idle (100s)\fR" ++/* The maximum amount of time that an idle Postfix daemon process waits ++/* for an incoming connection before terminating voluntarily. ++/* .IP "\fBmax_use (100)\fR" ++/* The maximal number of incoming connections that a Postfix daemon ++/* process will service before terminating voluntarily. ++/* .IP "\fBprocess_id (read-only)\fR" ++/* The process ID of a Postfix command or daemon process. ++/* .IP "\fBprocess_name (read-only)\fR" ++/* The process name of a Postfix command or daemon process. ++/* .IP "\fBqueue_directory (see 'postconf -d' output)\fR" ++/* The location of the Postfix top-level queue directory. ++/* .IP "\fBsyslog_facility (mail)\fR" ++/* The syslog facility of Postfix logging. ++/* .IP "\fBsyslog_name (postfix)\fR" ++/* The mail system name that is prepended to the process name in syslog ++/* records, so that "smtpd" becomes, for example, "postfix/smtpd". ++/* SEE ALSO ++/* qmgr(8), queue manager ++/* bounce(8), delivery status reports ++/* postconf(5), configuration parameters ++/* syslogd(8), system logging ++/* README_FILES ++/* Use "\fBpostconf readme_directory\fR" or ++/* "\fBpostconf html_directory\fR" to locate this information. ++/* VIRTUAL_README, domain hosting howto ++/* LICENSE ++/* .ad ++/* .fi ++/* The Secure Mailer license must be distributed with this software. ++/* HISTORY ++/* .ad ++/* .fi ++/* This delivery agent was originally based on the Postfix local delivery ++/* agent. Modifications mainly consisted of removing code that either ++/* was not applicable or that was not safe in this context: aliases, ++/* ~user/.forward files, delivery to "|command" or to /file/name. ++/* ++/* The \fBDelivered-To:\fR message header appears in the \fBqmail\fR ++/* system by Daniel Bernstein. ++/* ++/* The \fBmaildir\fR structure appears in the \fBqmail\fR system ++/* by Daniel Bernstein. ++/* AUTHOR(S) ++/* Wietse Venema ++/* IBM T.J. Watson Research ++/* P.O. Box 704 ++/* Yorktown Heights, NY 10598, USA ++/* ++/* Andrew McNamara ++/* andrewm@connect.com.au ++/* connect.com.au Pty. Ltd. ++/* Level 3, 213 Miller St ++/* North Sydney 2060, NSW, Australia ++/*--*/ ++ ++/* System library. */ ++ ++#include <sys_defs.h> ++#include <stdlib.h> ++#ifdef USE_PATHS_H ++#include <paths.h> /* XXX mail_spool_dir dependency */ ++#endif ++ ++/* Utility library. */ ++ ++#include <msg.h> ++#include <vstring.h> ++#include <vstream.h> ++#include <iostuff.h> ++#include <set_eugid.h> ++#include <dict.h> ++ ++/* Global library. */ ++ ++#include <mail_queue.h> ++#include <recipient_list.h> ++#include <deliver_request.h> ++#include <deliver_completed.h> ++#include <mail_params.h> ++#include <mail_version.h> ++#include <mail_conf.h> ++#include <mail_params.h> ++#include <mail_addr_find.h> ++#include <flush_clnt.h> ++ ++/* Single server skeleton. */ ++ ++#include <mail_server.h> ++ ++/* Application-specific. */ ++ ++#include "virtual.h" ++ ++ /* ++ * Tunable parameters. ++ */ ++char *var_virt_mailbox_maps; ++char *var_virt_uid_maps; ++char *var_virt_gid_maps; ++int var_virt_minimum_uid; ++char *var_virt_mailbox_base; ++char *var_virt_mailbox_lock; ++int var_virt_mailbox_limit; ++char *var_mail_spool_dir; /* XXX dependency fix */ ++ ++ /* ++ * Mappings. ++ */ ++MAPS *virtual_mailbox_maps; ++MAPS *virtual_uid_maps; ++MAPS *virtual_gid_maps; ++ ++ /* ++ * Bit masks. ++ */ ++int virtual_mbox_lock_mask; ++ ++/* local_deliver - deliver message with extreme prejudice */ ++ ++static int local_deliver(DELIVER_REQUEST *rqst, char *service) ++{ ++ const char *myname = "local_deliver"; ++ RECIPIENT *rcpt_end = rqst->rcpt_list.info + rqst->rcpt_list.len; ++ RECIPIENT *rcpt; ++ int rcpt_stat; ++ int msg_stat; ++ LOCAL_STATE state; ++ USER_ATTR usr_attr; ++ ++ if (msg_verbose) ++ msg_info("local_deliver: %s from %s", rqst->queue_id, rqst->sender); ++ ++ /* ++ * Initialize the delivery attributes that are not recipient specific. ++ */ ++ state.level = 0; ++ deliver_attr_init(&state.msg_attr); ++ state.msg_attr.queue_name = rqst->queue_name; ++ state.msg_attr.queue_id = rqst->queue_id; ++ state.msg_attr.fp = rqst->fp; ++ state.msg_attr.offset = rqst->data_offset; ++ state.msg_attr.sender = rqst->sender; ++ state.msg_attr.dsn_envid = rqst->dsn_envid; ++ state.msg_attr.dsn_ret = rqst->dsn_ret; ++ state.msg_attr.relay = service; ++ state.msg_attr.msg_stats = rqst->msg_stats; ++ RESET_USER_ATTR(usr_attr, state.level); ++ state.request = rqst; ++ ++ /* ++ * Iterate over each recipient named in the delivery request. When the ++ * mail delivery status for a given recipient is definite (i.e. bounced ++ * or delivered), update the message queue file and cross off the ++ * recipient. Update the per-message delivery status. ++ */ ++ for (msg_stat = 0, rcpt = rqst->rcpt_list.info; rcpt < rcpt_end; rcpt++) { ++ state.msg_attr.rcpt = *rcpt; ++ rcpt_stat = deliver_recipient(state, usr_attr); ++ if (rcpt_stat == 0 && (rqst->flags & DEL_REQ_FLAG_SUCCESS)) ++ deliver_completed(state.msg_attr.fp, rcpt->offset); ++ msg_stat |= rcpt_stat; ++ } ++ ++ deliver_attr_free(&state.msg_attr); ++ return (msg_stat); ++} ++ ++/* local_service - perform service for client */ ++ ++static void local_service(VSTREAM *stream, char *service, char **argv) ++{ ++ DELIVER_REQUEST *request; ++ int status; ++ ++ /* ++ * Sanity check. This service takes no command-line arguments. ++ */ ++ if (argv[0]) ++ msg_fatal("unexpected command-line argument: %s", argv[0]); ++ ++ /* ++ * This routine runs whenever a client connects to the UNIX-domain socket ++ * that is dedicated to local mail delivery service. What we see below is ++ * a little protocol to (1) tell the client that we are ready, (2) read a ++ * delivery request from the client, and (3) report the completion status ++ * of that request. ++ */ ++ if ((request = deliver_request_read(stream)) != 0) { ++ status = local_deliver(request, service); ++ deliver_request_done(stream, request, status); ++ } ++} ++ ++/* pre_accept - see if tables have changed */ ++ ++static void pre_accept(char *unused_name, char **unused_argv) ++{ ++ const char *table; ++ ++ if ((table = dict_changed_name()) != 0) { ++ msg_info("table %s has changed -- restarting", table); ++ exit(0); ++ } ++} ++ ++/* post_init - post-jail initialization */ ++ ++static void post_init(char *unused_name, char **unused_argv) ++{ ++ ++ /* ++ * Drop privileges most of the time. ++ */ ++ set_eugid(var_owner_uid, var_owner_gid); ++ ++ /* ++ * No case folding needed: the recipient address is case folded. ++ */ ++ virtual_mailbox_maps = ++ maps_create(VAR_VIRT_MAILBOX_MAPS, var_virt_mailbox_maps, ++ DICT_FLAG_LOCK | DICT_FLAG_PARANOID); ++ ++ virtual_uid_maps = ++ maps_create(VAR_VIRT_UID_MAPS, var_virt_uid_maps, ++ DICT_FLAG_LOCK | DICT_FLAG_PARANOID); ++ ++ virtual_gid_maps = ++ maps_create(VAR_VIRT_GID_MAPS, var_virt_gid_maps, ++ DICT_FLAG_LOCK | DICT_FLAG_PARANOID); ++ ++ virtual_mbox_lock_mask = mbox_lock_mask(var_virt_mailbox_lock); ++} ++ ++/* pre_init - pre-jail initialization */ ++ ++static void pre_init(char *unused_name, char **unused_argv) ++{ ++ ++ /* ++ * Reset the file size limit from the message size limit to the mailbox ++ * size limit. ++ * ++ * We can't have mailbox size limit smaller than the message size limit, ++ * because that prohibits the delivery agent from updating the queue ++ * file. ++ */ ++ if (var_virt_mailbox_limit) { ++ if (var_virt_mailbox_limit < var_message_limit || var_message_limit == 0) ++ msg_fatal("main.cf configuration error: %s is smaller than %s", ++ VAR_VIRT_MAILBOX_LIMIT, VAR_MESSAGE_LIMIT); ++ set_file_limit(var_virt_mailbox_limit); ++ } ++ ++ /* ++ * flush client. ++ */ ++ flush_init(); ++} ++ ++MAIL_VERSION_STAMP_DECLARE; ++ ++/* main - pass control to the single-threaded skeleton */ ++ ++int main(int argc, char **argv) ++{ ++ static const CONFIG_INT_TABLE int_table[] = { ++ VAR_VIRT_MINUID, DEF_VIRT_MINUID, &var_virt_minimum_uid, 1, 0, ++ VAR_VIRT_MAILBOX_LIMIT, DEF_VIRT_MAILBOX_LIMIT, &var_virt_mailbox_limit, 0, 0, ++ 0, ++ }; ++ static const CONFIG_STR_TABLE str_table[] = { ++ VAR_MAIL_SPOOL_DIR, DEF_MAIL_SPOOL_DIR, &var_mail_spool_dir, 0, 0, ++ VAR_VIRT_MAILBOX_MAPS, DEF_VIRT_MAILBOX_MAPS, &var_virt_mailbox_maps, 0, 0, ++ VAR_VIRT_UID_MAPS, DEF_VIRT_UID_MAPS, &var_virt_uid_maps, 0, 0, ++ VAR_VIRT_GID_MAPS, DEF_VIRT_GID_MAPS, &var_virt_gid_maps, 0, 0, ++ VAR_VIRT_MAILBOX_BASE, DEF_VIRT_MAILBOX_BASE, &var_virt_mailbox_base, 1, 0, ++ VAR_VIRT_MAILBOX_LOCK, DEF_VIRT_MAILBOX_LOCK, &var_virt_mailbox_lock, 1, 0, ++ 0, ++ }; ++ ++ /* ++ * Fingerprint executables and core dumps. ++ */ ++ MAIL_VERSION_STAMP_ALLOCATE; ++ ++ single_server_main(argc, argv, local_service, ++ MAIL_SERVER_INT_TABLE, int_table, ++ MAIL_SERVER_STR_TABLE, str_table, ++ MAIL_SERVER_PRE_INIT, pre_init, ++ MAIL_SERVER_POST_INIT, post_init, ++ MAIL_SERVER_PRE_ACCEPT, pre_accept, ++ MAIL_SERVER_PRIVILEGED, ++ 0); ++} +diff -Nru postfix-2.5.1/src/virtual/virtual.h postfix-2.5.1-vda-ng/src/virtual/virtual.h +--- postfix-2.5.1/src/virtual/virtual.h 2006-01-08 00:59:47.000000000 +0100 ++++ postfix-2.5.1-vda-ng/src/virtual/virtual.h 2008-03-15 15:06:02.103665796 +0100 @@ -34,6 +34,9 @@ extern MAPS *virtual_mailbox_maps; extern MAPS *virtual_uid_maps; |