From e9bbf68245cc4f7d015e463b5c0c95008fd382e3 Mon Sep 17 00:00:00 2001 From: Peter Pentchev Date: Tue, 9 Oct 2007 13:27:24 +0000 Subject: Update vpopmail to 5.4.20 after a long delay, mostly due to wondering how to handle the database upgrade and the SpamAssassin patch partial integration. There are several important changes that may affect your vpopmail installation and may need you to handle manually: - THE MYSQL CONNECTION INFORMATION IS NO LONGER DEFINED AT COMPILE-TIME! The WITH_MYSQL_{USER,PASSWD,SERVER,DB} variables should NOT be defined when you build the port; place that information in the vpopmail.mysql file after vpopmail has been installed! - the default domain is also no longer defined at compile time - you need to place it in the defaultdomain file after the installation. - the defaultdomain and vpopmail.mysql files are no longer blindly removed on deinstallation, they are only removed if they have not been modified - in vpopmail 5.4.18, the database schema was changed - some fields were extended from 64 to 96 characters. If you do not apply those changes to your database, as explained in the vpopmail/doc/UPGRADE file, your vpopmail installation may silently fail or lose the trailing portions of domain names and usernames. - in vpopmail 5.4.19, the upstream authors integrated large parts of Alex Dupre's SpamAssassin support, without the SPAM_THRESHOLD part. If you use vpopmail along with the SpamAssassin FreeBSD port support, take extra care to ensure that your installation still processes e-mail messages in the same way. - vpopmail 5.4.19 added support for maildrop as a mail delivery agent. This is available in the FreeBSD port if WITH_MAILDROP is defined. There is also a new user-limit flag for maildrop delivery. - vpopmail 5.4.19 added support for MySQL connections via Unix sockets instead of TCP sockets to the server. To do that, change the second value (the port number) in vpopmail.mysql to the full pathname of the MySQL socket (e.g. /tmp/mysql.sock). - vpopmail 5.4.20 extended the LDAP support; please see README.ldap for more information, and specify the LDAP connection information in the vpopmail/etc/vpopmail.ldap file after the installation. --- mail/vpopmail/files/patch-vdelivermail.c | 341 ++----------------------------- 1 file changed, 19 insertions(+), 322 deletions(-) (limited to 'mail/vpopmail/files/patch-vdelivermail.c') diff --git a/mail/vpopmail/files/patch-vdelivermail.c b/mail/vpopmail/files/patch-vdelivermail.c index d324a7f820f1..010b03d8c317 100644 --- a/mail/vpopmail/files/patch-vdelivermail.c +++ b/mail/vpopmail/files/patch-vdelivermail.c @@ -1,324 +1,21 @@ -diff -urN -x .svn ../../vendor/vpopmail/vdelivermail.c ./vdelivermail.c ---- ../../vendor/vpopmail/vdelivermail.c Wed Oct 4 13:19:16 2006 -+++ ./vdelivermail.c Wed Oct 4 15:44:20 2006 -@@ -66,6 +66,7 @@ - - #define FILE_SIZE 156 - char loop_buf[FILE_SIZE]; -+char spam_buf[FILE_SIZE]; - - #define MSG_BUF_SIZE 5000 - char msgbuf[MSG_BUF_SIZE]; -@@ -78,9 +79,6 @@ - #define EXIT_OK 0 - #define EXIT_OVERQUOTA EXIT_BOUNCE - --/* from qmail's wait.h for run_command() */ --#define wait_exitcode(w) ((w) >> 8) -- - /* Forward declarations */ - int process_valias(void); - void get_arguments(int argc, char **argv); -@@ -93,7 +91,10 @@ - void usernotfound(void); - int is_loop_match( const char *dt, const char *address); - int deliver_quota_warning(const char *dir, const char *q); -- -+#ifdef SPAM_THRESHOLD -+int is_spam(int threshold); -+int is_spam_match(char *xsl, int threshold); -+#endif - - /* print an error string and then exit - * vexit() never returns, so vexiterr() and vexit() should actually return void -@@ -201,7 +202,7 @@ - if ( is_domain_valid(TheDomain) != 0 ) - vexiterr (EXIT_BOUNCE, "invalid domain name"); - -- strncpy(TheUserFull, TheUser, sizeof(TheUserFull)); -+ snprintf (TheUserFull, sizeof(TheUserFull), "%s", TheUser); - - #ifdef QMAIL_EXT - /* !! Shouldn't this work its way backwards, and try all possibilities? -@@ -247,7 +248,7 @@ - - /* check for wildcard if there's no match */ - if(tmpstr == NULL) { -- for(i=strlen(TheUser);i >= 0 && j != 1;--i) { -+ for(i=strlen(TheUser);i > 0 && j != 1;--i) { - if(TheUser[i-1]=='-') { - tmpuser[0] = '\0'; - strncat(tmpuser,TheUser,i); -@@ -410,6 +411,10 @@ - char local_file_new[FILE_SIZE]; - size_t headerlen; - int write_fd; -+#ifdef SPAMC -+ int nread; -+ int pim[2]; -+#endif - char quota[80]; - - headerlen = strlen (extra_headers); -@@ -435,6 +440,49 @@ - return(-2); - } - -+#ifdef SPAMC -+ /* fork the SpamAssassin client - patch by Alex Dupre */ -+ if (!pipe(pim)) { -+ pid = vfork(); -+ switch (pid) { -+ case -1: -+ close(pim[0]); -+ close(pim[1]); -+ break; -+ case 0: -+ close(pim[0]); -+ dup2(pim[1], 1); -+ close(pim[1]); -+ if (execl(SPAMC, SPAMC, "-u", maildir_to_email(maildir), 0) == -1) { -+ while ((nread = read(0, msgbuf, MSG_BUF_SIZE)) > 0) -+ write(1, msgbuf, nread); -+ _exit(0); -+ } -+ } -+ close(pim[1]); -+ dup2(pim[0], 0); -+ close(pim[0]); -+ } -+#ifdef SPAM_THRESHOLD -+ /* silently delete message if spam level > SPAM_THRESHOLD */ -+ if (is_spam(SPAM_THRESHOLD) == 1) { -+ close(write_fd); -+ unlink(local_file_tmp); -+ return 0; -+ } -+ -+#ifdef MAKE_SEEKABLE -+ if (!Seekable(0)) -+ MakeSeekable(stdin); -+#endif -+ -+ if (lseek(0, 0L, SEEK_SET) < 0) { -+ printf("lseek errno=%d\n", errno); -+ return -2; -+ } -+#endif +diff -urN -x .svn ../../../branches/vendor/vpopmail/vdelivermail.c ./vdelivermail.c +--- ../../../branches/vendor/vpopmail/vdelivermail.c 2007-10-07 19:56:56.000000000 +0300 ++++ ./vdelivermail.c 2007-10-07 21:18:56.000000000 +0300 +@@ -1246,7 +1246,17 @@ + } + + /* still in the headers check for spam header */ ++#ifndef SPAM_THRESHOLD + if ( strncmp(&spambuf[j], "X-Spam-Flag: YES", 16 ) == 0 ) return(1); ++#else ++ if ( strncmp(&spambuf[j], "X-Spam-Level: ", 14 ) == 0 ) { ++ for (k = 0; k < SPAM_THRESHOLD; k++) { ++ if (spambuf[j + 14 + k] != '*') ++ return (0); ++ } ++ return(1); ++ } +#endif -+ - if (fdcopy (write_fd, read_fd, extra_headers, headerlen) != 0) { - /* Did the write fail because we were over quota? */ - if ( errno == EDQUOT ) { -@@ -549,10 +597,10 @@ - if (user_over_maildirquota(address,format_maildirquota(quota))==1) { - /* check for over quota message in domain */ -- sprintf(tmp_file, "%s/.over-quota.msg",TheDomainDir); -+ snprintf(tmp_file, sizeof(tmp_file), "%s/.over-quota.msg",TheDomainDir); - if ( (fs=fopen(tmp_file, "r")) == NULL ) { - /* if no domain over quota then check in vpopmail dir */ -- sprintf(tmp_file, "%s/%s/.over-quota.msg",VPOPMAILDIR,DOMAINS_DIR); -+ snprintf(tmp_file, sizeof(tmp_file), "%s/%s/.over-quota.msg",VPOPMAILDIR,DOMAINS_DIR); - fs=fopen(tmp_file, "r"); - } - -@@ -579,10 +627,10 @@ - if (domain_over_maildirquota(address)==1) - { - /* check for over quota message in domain */ -- sprintf(tmp_file, "%s/.over-quota.msg",TheDomainDir); -+ snprintf(tmp_file, sizeof(tmp_file), "%s/.over-quota.msg",TheDomainDir); - if ( (fs=fopen(tmp_file, "r")) == NULL ) { - /* if no domain over quota then check in vpopmail dir */ -- sprintf(tmp_file, "%s/%s/.over-quota.msg",VPOPMAILDIR,DOMAINS_DIR); -+ snprintf(tmp_file, sizeof(tmp_file), "%s/%s/.over-quota.msg",VPOPMAILDIR,DOMAINS_DIR); - fs=fopen(tmp_file, "r"); - } - -@@ -673,9 +721,12 @@ - } - - close(fdm); -- waitpid(inject_pid,&child,0); -- xcode = wait_exitcode(child); -- if (xcode == 0) return; -+ if (waitpid(inject_pid,&child,0) <= 0 || !WIFEXITED(child)) { -+ xcode = EXIT_DEFER; -+ } else { -+ xcode = WEXITSTATUS(child); -+ if (xcode == 0) return; -+ } - vexiterr (xcode, "system error calling qmail-inject"); - } - } -@@ -775,6 +826,7 @@ - printf("Unable to fork: %d.", errno); - vexit(EXIT_DEFER); - case 0: -+ setenv("SHELL", "/bin/sh", 1); - args[0] = "/bin/sh"; args[1] = "-c"; args[2] = prog; args[3] = 0; - sig_catch(SIGPIPE,SIG_DFL); - execv(*args,args); -@@ -782,9 +834,9 @@ - exit(EXIT_DEFER); /* the child's exit code will get caught below */ - } - -- wait(&wstat); -- waitpid(wstat,&child,0); -- switch(wait_exitcode(wstat)) -+ if (waitpid(child,&wstat,0) < 0 || !WIFEXITED(wstat)) -+ vexit(EXIT_DEFER); -+ switch(WEXITSTATUS(wstat)) - { - case 64: case 65: case 70: case 76: case 77: case 78: case 100: case 112: vexit(EXIT_BOUNCE); - case 99: vexit(99); /* not sure about this, when does it exit 99? */ -@@ -830,9 +882,13 @@ - - /* if we find the line, return error (looping) */ - if (is_loop_match(loop_buf, address)==1 ) { -+ /* seek to the end of stdin */ -+ fseek(stdin, 0L, SEEK_END); - /* return the loop found */ - return(1); - } else if (*loop_buf == '\r' || *loop_buf == '\n') { -+ /* seek to the end of stdin */ -+ fseek(stdin, 0L, SEEK_END); - /* end of headers return not found looping message value */ - return(0); - } -@@ -949,10 +1005,10 @@ - FILE *fs; - char tmp_file[256]; - -- sprintf(tmp_file, "%s/.no-user.msg",TheDomainDir); -+ snprintf(tmp_file, sizeof(tmp_file), "%s/.no-user.msg",TheDomainDir); - if ( (fs=fopen(tmp_file, "r")) == NULL ) { - /* if no domain no user then check in vpopmail dir */ -- sprintf(tmp_file, "%s/%s/.no-user.msg",VPOPMAILDIR,DOMAINS_DIR); -+ snprintf(tmp_file, sizeof(tmp_file), "%s/%s/.no-user.msg",VPOPMAILDIR,DOMAINS_DIR); - fs=fopen(tmp_file, "r"); - } - if ( fs == NULL ) { -@@ -999,7 +1055,7 @@ - struct stat sb; - char quotawarnmsg[BUFF_SIZE]; - -- sprintf (quotawarnmsg, "%s%s", dir, "/quotawarn"); -+ snprintf (quotawarnmsg, sizeof(quotawarnmsg), "%s%s", dir, "/quotawarn"); - time(&tm); - - /* Send only one warning every 24 hours */ -@@ -1017,12 +1073,12 @@ - close(fd); - - /* Look in the domain for a .quotawarn.msg */ -- sprintf(quotawarnmsg, "%s/.quotawarn.msg", TheDomainDir); -+ snprintf(quotawarnmsg, sizeof(quotawarnmsg), "%s/.quotawarn.msg", TheDomainDir); - if ( ((read_fd = open(quotawarnmsg, O_RDONLY)) < 0) || - (stat(quotawarnmsg, &sb) != 0)) { - - /* if that fails look in vpopmail dir */ -- sprintf(quotawarnmsg, "%s/%s/.quotawarn.msg", VPOPMAILDIR, DOMAINS_DIR); -+ snprintf(quotawarnmsg, sizeof(quotawarnmsg), "%s/%s/.quotawarn.msg", VPOPMAILDIR, DOMAINS_DIR); - if ( ((read_fd = open(quotawarnmsg, O_RDONLY)) < 0) || - (stat(quotawarnmsg, &sb) != 0)) { - return 0; -@@ -1063,3 +1119,97 @@ - - return (strcasecmp (compare, (dt+14)) == 0); - } -+ -+#ifdef SPAM_THRESHOLD -+/* Check for a spam message -+ * This is done by checking for a matching line -+ * in the email headers for X-Spam-Level: which -+ * we put in each spam email -+ * -+ * Return 1 if spam -+ * Return 0 if not spam -+ * Return -1 on error -+ */ -+int is_spam(int threshold) -+{ -+ int i; -+ int found; -+ -+#ifdef MAKE_SEEKABLE -+ if (!Seekable(0)) -+ MakeSeekable(stdin); -+#endif -+ -+ if ( lseek(0, 0L, SEEK_SET) < 0 ) { -+ printf("lseek errno=%d\n", errno); -+ return(-1); -+ } -+ -+ while (fgets(spam_buf, sizeof(spam_buf), stdin) != NULL){ -+ -+ /* if we find the line, return error (looping) */ -+ if (strncmp(spam_buf, "X-Spam-Level: ", 14) == 0 && -+ is_spam_match(spam_buf, threshold) ==1) { -+ -+ /* seek to the end of stdin */ -+ lseek(0, 0L, SEEK_END); -+ -+ /* return the spam found */ -+ return(1); -+ -+ /* check for the start of the body, we only need -+ * to check the headers. -+ */ -+ } else { -+ -+ /* walk through the charaters in the body */ -+ for (i = 0, found = 0; spam_buf[i] != 0 && found == 0; ++i) { -+ switch(spam_buf[i]) { -+ -+ /* skip blank spaces and new lines */ -+ case ' ': -+ case '\n': -+ case '\t': -+ case '\r': -+ break; -+ -+ /* found a non blank, so we are still -+ * in the headers -+ */ -+ default: -+ -+ /* set the found non blank char flag */ -+ found = 1; -+ break; -+ } -+ } -+ -+ /* if the line only had blanks, then it is the -+ * delimiting line between the headers and the -+ * body. We don't need to check the body for -+ * the X-Spam-Level: line. Hence, we -+ * are done with our search and can return the -+ * spam not found value -+ */ -+ if (found == 0) { -+ /* seek to the end of stdin */ -+ lseek(0, 0L, SEEK_END); -+ /* return not found spam message value */ -+ return(0); -+ } -+ } -+ } -+ -+ /* if we get here then there is either no body -+ * or SpamAssassin drop it, so mark the message -+ * as spam. -+ */ -+ return(1); -+} -+ -+int is_spam_match(char *xsl, int threshold) -+{ -+ if (strlen(xsl) - strlen("X-Spam-Level: ") > threshold) return(1); -+ else return(0); -+} -+#endif + if (spambuf[i+1]!=0) j=i+1; + } -- cgit v1.2.3