diff --git a/mail/exim/Makefile b/mail/exim/Makefile index f0161a3c4237..7fce654ea95d 100644 --- a/mail/exim/Makefile +++ b/mail/exim/Makefile @@ -3,7 +3,7 @@ PORTNAME= exim PORTVERSION?= ${EXIM_VERSION} -PORTREVISION= 2 +PORTREVISION= 3 CATEGORIES= mail ipv6 MASTER_SITES= ${MASTER_SITE_EXIM:S/$/:exim/} MASTER_SITE_SUBDIR= exim4/:exim @@ -57,7 +57,6 @@ PGSQL_USE= pgsql=yes REDIS_LIB_DEPENDS= libhiredis.so:${PORTSDIR}/databases/hiredis SASLAUTHD_RUN_DEPENDS= ${LOCALBASE}/sbin/saslauthd:${PORTSDIR}/security/cyrus-sasl2-saslauthd SA_EXIM_RUN_DEPENDS= ${LOCALBASE}/bin/spamc:${PORTSDIR}/mail/spamassassin -SO_1024_LDFLAGS= -lz SPF_LIB_DEPENDS= libspf2.so:${PORTSDIR}/mail/libspf2 SQLITE_USE= sqlite=yes SQLITE_USES= pkgconfig @@ -88,14 +87,8 @@ MASTER_SITE_SUBDIR+= sa-exim/:sa_exim DISTFILES+= sa-exim-${SA_EXIM_VERSION}.tar.gz:sa_exim .endif -.if ${PORT_OPTIONS:MSO_1024} || defined(FETCH_ALL) -MASTER_SITES+= ftp://ftp.renatasystems.org/pub/FreeBSD/ports/distfiles/:so_1024 -DISTFILES+= spamooborona1024-src-${SO_1024_VERSION}.tar.gz:so_1024 -.endif - EXIM_VERSION= 4.83 SA_EXIM_VERSION=4.2 -SO_1024_VERSION=3.2 EXIM_INSTALL_ARG+= "-no_chown" "-no_symlink" .if !defined(EXIMON_ONLY) @@ -519,10 +512,6 @@ post-extract: .if ${PORT_OPTIONS:MSA_EXIM} @cd ${WRKDIR} && ${TAR} ${EXTRACT_BEFORE_ARGS} ${_DISTDIR}/sa-exim-${SA_EXIM_VERSION}.tar.gz ${EXTRACT_AFTER_ARGS} .endif -.if ${PORT_OPTIONS:MSO_1024} - @cd ${WRKDIR} && ${TAR} ${EXTRACT_BEFORE_ARGS} ${_DISTDIR}/spamooborona1024-src-${SO_1024_VERSION}.tar.gz ${EXTRACT_AFTER_ARGS} - @cd ${WRKDIR} && ${PATCH} --quiet < ${FILESDIR}/extra-patch-so_1024-delimiter -.endif do-configure: @${MKDIR} ${WRKSRC}/Local @@ -549,11 +538,6 @@ do-configure: } > ${WRKSRC}/Local/sa-exim.h @${REINPLACE_CMD} -e 's,/usr/bin/spamc,${LOCALBASE}/bin/spamc,' \ ${WRKDIR}/sa-exim-${SA_EXIM_VERSION}/sa-exim.conf -.endif -.if ${PORT_OPTIONS:MSO_1024} - @${REINPLACE_CMD} -E -e 's/^(LOCAL_SCAN_SOURCE=).*/\1Local\/local_scan_1024.c/' \ - ${WRKSRC}/OS/Makefile-Default - @${CP} ${WRKDIR}/local_scan_1024.c ${WRKSRC}/Local .endif @${REINPLACE_CMD} -E -e 's/XX_STRIPCMD_XX/${STRIP_CMD:S,/,\/,g}/' \ ${WRKSRC}/OS/Makefile-FreeBSD @@ -576,9 +560,6 @@ post-install: .for script in ${DAILY_SCRIPTS} ${INSTALL_SCRIPT} ${WRKDIR}/${script}.sh ${STAGEDIR}${PREFIX}/etc/periodic/daily/${script} .endfor -.endif -.if ${PORT_OPTIONS:MSO_1024} - @${MKDIR} -m 750 ${STAGEDIR}var/spool/spamooborona .endif @${MKDIR} -m 750 ${STAGEDIR}${LOGDIR} @${INSTALL_MAN} ${WRKSRC}/doc/exim.8 ${STAGEDIR}${MAN8PREFIX}/man/man8 diff --git a/mail/exim/distinfo b/mail/exim/distinfo index 3c9ca47bf80b..c88607586449 100644 --- a/mail/exim/distinfo +++ b/mail/exim/distinfo @@ -2,5 +2,3 @@ SHA256 (exim/exim-4.83.tar.bz2) = efa031b89ffb2ab844a4bf9d3a5d7ca4d587d82b62ae23 SIZE (exim/exim-4.83.tar.bz2) = 1761169 SHA256 (exim/sa-exim-4.2.tar.gz) = 72e0a735547f18b05785e6c58a71d24623858f0f5234a5dc0e24cb453999e99a SIZE (exim/sa-exim-4.2.tar.gz) = 66575 -SHA256 (exim/spamooborona1024-src-3.2.tar.gz) = ab22a430f3860460045f6b213c68c89700a0cd10cbb6c7a808ece326c53787ee -SIZE (exim/spamooborona1024-src-3.2.tar.gz) = 8537 diff --git a/mail/exim/files/POST-INSTALL-NOTES b/mail/exim/files/POST-INSTALL-NOTES index f6df1feabe85..b264ec723768 100644 --- a/mail/exim/files/POST-INSTALL-NOTES +++ b/mail/exim/files/POST-INSTALL-NOTES @@ -30,7 +30,7 @@ To use Exim instead of sendmail on startup: 'daily_submit_queuerun' to "NO" in periodic.conf(5), if you intend to manage queue runners / deliveries closely. *) Set the 'exim_enable' rc.conf(5) variable to 'YES'. -*) Start exim with '%%RC_DIR%%/exim%%RC_SUFX%% start'. +*) Start exim with '%%PREFIX%%/etc/rc.d/exim start'. You may also want to configure newsyslog(8) to rotate Exim log files: diff --git a/mail/exim/files/extra-patch-so_1024-delimiter b/mail/exim/files/extra-patch-so_1024-delimiter deleted file mode 100644 index 382d3e7cc308..000000000000 --- a/mail/exim/files/extra-patch-so_1024-delimiter +++ /dev/null @@ -1,13 +0,0 @@ -Taken from: http://timofeev.biz/2010/10/14/151 - ---- local_scan_1024.c 2009-11-27 14:02:06.000000000 +0300 -+++ local_scan_1024.c 2012-12-30 22:18:53.491544089 +0400 -@@ -443,7 +443,7 @@ - if (strncmp (answ, "SODAEMON ", 9) == 0) - { - strP = (char*) answ; -- for (tok = strtok (strP, "\n"); tok; tok = strtok (NULL, "\n")) -+ for (tok = strtok (strP, "\r\n"); tok; tok = strtok (NULL, "\r\n")) - { - /* signature always goes first */ - if (strncmp (tok, "SODAEMON ", 9) == 0) diff --git a/mail/exim/files/patch-src__mime.c b/mail/exim/files/patch-src__mime.c new file mode 100644 index 000000000000..37482c73135a --- /dev/null +++ b/mail/exim/files/patch-src__mime.c @@ -0,0 +1,1191 @@ +X-Git-Url: http://git.exim.org/exim.git/blobdiff_plain/1bd0d12bcbf4f51bd78c60d5bae01f1ff38c5a84..4fd5d2bf25195969b9c6a6c23a59c495400ece8d:/src/src/mime.c + +diff --git a/src/src/mime.c b/src/src/mime.c +index 2233dac..95d3da4 100644 +--- src/mime.c ++++ src/mime.c +@@ -6,7 +6,7 @@ + /* License: GPL */ + + #include "exim.h" +-#ifdef WITH_CONTENT_SCAN ++#ifdef WITH_CONTENT_SCAN /* entire file */ + #include "mime.h" + #include + +@@ -21,7 +21,9 @@ uschar *mime_current_boundary = NULL; + give info on detected "problems" in MIME + encodings. Those are defined in mime.h. */ + +-void mime_set_anomaly(int level, const char *text) { ++void ++mime_set_anomaly(int level, const char *text) ++{ + mime_anomaly_level = level; + mime_anomaly_text = CUS text; + } +@@ -39,36 +41,37 @@ void mime_set_anomaly(int level, const char *text) { + 0-255 - char to write + */ + +-uschar *mime_decode_qp_char(uschar *qp_p, int *c) { +- uschar *initial_pos = qp_p; ++uschar * ++mime_decode_qp_char(uschar *qp_p, int *c) ++{ ++uschar *initial_pos = qp_p; ++ ++/* advance one char */ ++qp_p++; ++ ++/* Check for two hex digits and decode them */ ++if (isxdigit(*qp_p) && isxdigit(qp_p[1])) ++ { ++ /* Do hex conversion */ ++ *c = (isdigit(*qp_p) ? *qp_p - '0' : toupper(*qp_p) - 'A' + 10) <<4; ++ qp_p++; ++ *c |= isdigit(*qp_p) ? *qp_p - '0' : toupper(*qp_p) - 'A' + 10; ++ return qp_p + 1; ++ } + +- /* advance one char */ ++/* tab or whitespace may follow just ignore it if it precedes \n */ ++while (*qp_p == '\t' || *qp_p == ' ' || *qp_p == '\r') + qp_p++; + +- /* Check for two hex digits and decode them */ +- if (isxdigit(*qp_p) && isxdigit(qp_p[1])) { +- /* Do hex conversion */ +- if (isdigit(*qp_p)) {*c = *qp_p - '0';} +- else {*c = toupper(*qp_p) - 'A' + 10;}; +- *c <<= 4; +- if (isdigit(qp_p[1])) {*c |= qp_p[1] - '0';} +- else {*c |= toupper(qp_p[1]) - 'A' + 10;}; +- return qp_p + 2; +- }; +- +- /* tab or whitespace may follow just ignore it if it precedes \n */ +- while (*qp_p == '\t' || *qp_p == ' ' || *qp_p == '\r') +- qp_p++; +- +- if (*qp_p == '\n') { +- /* hit soft line break */ +- *c = -1; +- return qp_p; +- }; +- +- /* illegal char here */ +- *c = -2; +- return initial_pos; ++if (*qp_p == '\n') /* hit soft line break */ ++ { ++ *c = -1; ++ return qp_p; ++ } ++ ++/* illegal char here */ ++*c = -2; ++return initial_pos; + } + + +@@ -79,18 +82,19 @@ mime_decode_asis(FILE* in, FILE* out, uschar* boundary) + ssize_t len, size = 0; + uschar buffer[MIME_MAX_LINE_LENGTH]; + +- while(fgets(CS buffer, MIME_MAX_LINE_LENGTH, mime_stream) != NULL) { ++ while(fgets(CS buffer, MIME_MAX_LINE_LENGTH, mime_stream) != NULL) ++ { + if (boundary != NULL +- && Ustrncmp(buffer, "--", 2) == 0 +- && Ustrncmp((buffer+2), boundary, Ustrlen(boundary)) == 0 +- ) ++ && Ustrncmp(buffer, "--", 2) == 0 ++ && Ustrncmp((buffer+2), boundary, Ustrlen(boundary)) == 0 ++ ) + break; + + len = Ustrlen(buffer); + if (fwrite(buffer, 1, (size_t)len, out) < len) + return -1; + size += len; +- } /* while */ ++ } /* while */ + return size; + } + +@@ -107,26 +111,29 @@ mime_decode_base64(FILE* in, FILE* out, uschar* boundary) + opos = obuf; + + while (Ufgets(ibuf, MIME_MAX_LINE_LENGTH, in) != NULL) +- { ++ { + if (boundary != NULL +- && Ustrncmp(ibuf, "--", 2) == 0 +- && Ustrncmp((ibuf+2), boundary, Ustrlen(boundary)) == 0 +- ) ++ && Ustrncmp(ibuf, "--", 2) == 0 ++ && Ustrncmp((ibuf+2), boundary, Ustrlen(boundary)) == 0 ++ ) + break; + +- for (ipos = ibuf ; *ipos != '\r' && *ipos != '\n' && *ipos != 0; ++ipos) { +- /* skip padding */ +- if (*ipos == '=') { ++ for (ipos = ibuf ; *ipos != '\r' && *ipos != '\n' && *ipos != 0; ++ipos) ++ { ++ if (*ipos == '=') /* skip padding */ ++ { + ++bytestate; + continue; +- } +- /* skip bad characters */ +- if (mime_b64[*ipos] == 128) { ++ } ++ if (mime_b64[*ipos] == 128) /* skip bad characters */ ++ { + mime_set_anomaly(MIME_ANOMALY_BROKEN_BASE64); + continue; +- } ++ } ++ + /* simple state-machine */ +- switch((bytestate++) & 3) { ++ switch((bytestate++) & 3) ++ { + case 0: + *opos = mime_b64[*ipos] << 2; + break; +@@ -144,27 +151,28 @@ mime_decode_base64(FILE* in, FILE* out, uschar* boundary) + *opos |= mime_b64[*ipos]; + ++opos; + break; +- } /* switch */ +- } /* for */ ++ } /* switch */ ++ } /* for */ ++ + /* something to write? */ + len = opos - obuf; +- if (len > 0) { +- if (fwrite(obuf, 1, len, out) != len) +- return -1; /* error */ ++ if (len > 0) ++ { ++ if (fwrite(obuf, 1, len, out) != len) return -1; /* error */ + size += len; + /* copy incomplete last byte to start of obuf, where we continue */ + if ((bytestate & 3) != 0) + *obuf = *opos; + opos = obuf; +- } +- } /* while */ ++ } ++ } /* while */ + + /* write out last byte if it was incomplete */ +- if (bytestate & 3) { +- if (fwrite(obuf, 1, 1, out) != 1) +- return -1; +- ++size; +- } ++ if (bytestate & 3) ++ { ++ if (fwrite(obuf, 1, 1, out) != 1) return -1; ++ ++size; ++ } + + return size; + } +@@ -174,219 +182,232 @@ mime_decode_base64(FILE* in, FILE* out, uschar* boundary) + static ssize_t + mime_decode_qp(FILE* in, FILE* out, uschar* boundary) + { +- uschar ibuf[MIME_MAX_LINE_LENGTH], obuf[MIME_MAX_LINE_LENGTH]; +- uschar *ipos, *opos; +- ssize_t len, size = 0; ++uschar ibuf[MIME_MAX_LINE_LENGTH], obuf[MIME_MAX_LINE_LENGTH]; ++uschar *ipos, *opos; ++ssize_t len, size = 0; + +- while (fgets(CS ibuf, MIME_MAX_LINE_LENGTH, in) != NULL) ++while (fgets(CS ibuf, MIME_MAX_LINE_LENGTH, in) != NULL) + { +- if (boundary != NULL +- && Ustrncmp(ibuf, "--", 2) == 0 +- && Ustrncmp((ibuf+2), boundary, Ustrlen(boundary)) == 0 +- ) +- break; /* todo: check for missing boundary */ ++ if (boundary != NULL ++ && Ustrncmp(ibuf, "--", 2) == 0 ++ && Ustrncmp((ibuf+2), boundary, Ustrlen(boundary)) == 0 ++ ) ++ break; /* todo: check for missing boundary */ + +- ipos = ibuf; +- opos = obuf; +- +- while (*ipos != 0) { +- if (*ipos == '=') { +- int decode_qp_result; +- +- ipos = mime_decode_qp_char(ipos, &decode_qp_result); ++ ipos = ibuf; ++ opos = obuf; + +- if (decode_qp_result == -2) { +- /* Error from decoder. ipos is unchanged. */ +- mime_set_anomaly(MIME_ANOMALY_BROKEN_QP); +- *opos = '='; +- ++opos; +- ++ipos; +- } +- else if (decode_qp_result == -1) { +- break; +- } +- else if (decode_qp_result >= 0) { +- *opos = decode_qp_result; +- ++opos; +- } ++ while (*ipos != 0) ++ { ++ if (*ipos == '=') ++ { ++ int decode_qp_result; ++ ++ ipos = mime_decode_qp_char(ipos, &decode_qp_result); ++ ++ if (decode_qp_result == -2) ++ { ++ /* Error from decoder. ipos is unchanged. */ ++ mime_set_anomaly(MIME_ANOMALY_BROKEN_QP); ++ *opos = '='; ++ ++opos; ++ ++ipos; ++ } ++ else if (decode_qp_result == -1) ++ break; ++ else if (decode_qp_result >= 0) ++ { ++ *opos = decode_qp_result; ++ ++opos; ++ } + } +- else { +- *opos = *ipos; +- ++opos; +- ++ipos; ++ else ++ { ++ *opos = *ipos; ++ ++opos; ++ ++ipos; + } + } +- /* something to write? */ +- len = opos - obuf; +- if (len > 0) { +- if (fwrite(obuf, 1, len, out) != len) +- return -1; /* error */ +- size += len; ++ /* something to write? */ ++ len = opos - obuf; ++ if (len > 0) ++ { ++ if (fwrite(obuf, 1, len, out) != len) return -1; /* error */ ++ size += len; + } + } +- return size; ++return size; + } + + +-FILE *mime_get_decode_file(uschar *pname, uschar *fname) { +- FILE *f = NULL; +- uschar *filename; ++FILE * ++mime_get_decode_file(uschar *pname, uschar *fname) ++{ ++FILE *f = NULL; ++uschar *filename; + +- filename = (uschar *)malloc(2048); ++filename = (uschar *)malloc(2048); + +- if ((pname != NULL) && (fname != NULL)) { +- (void)string_format(filename, 2048, "%s/%s", pname, fname); +- f = modefopen(filename,"wb+",SPOOL_MODE); +- } +- else if (pname == NULL) { +- f = modefopen(fname,"wb+",SPOOL_MODE); ++if (pname && fname) ++ { ++ (void)string_format(filename, 2048, "%s/%s", pname, fname); ++ f = modefopen(filename,"wb+",SPOOL_MODE); + } +- else if (fname == NULL) { +- int file_nr = 0; +- int result = 0; ++else if (!pname) ++ f = modefopen(fname,"wb+",SPOOL_MODE); ++else if (!fname) ++ { ++ int file_nr = 0; ++ int result = 0; ++ ++ /* must find first free sequential filename */ ++ do ++ { ++ struct stat mystat; ++ (void)string_format(filename, 2048, ++ "%s/%s-%05u", pname, message_id, file_nr++); ++ /* security break */ ++ if (file_nr >= 1024) ++ break; ++ result = stat(CS filename, &mystat); ++ } while(result != -1); + +- /* must find first free sequential filename */ +- do { +- struct stat mystat; +- (void)string_format(filename,2048,"%s/%s-%05u", pname, message_id, file_nr); +- file_nr++; +- /* security break */ +- if (file_nr >= 1024) +- break; +- result = stat(CS filename,&mystat); +- } +- while(result != -1); +- f = modefopen(filename,"wb+",SPOOL_MODE); +- }; ++ f = modefopen(filename, "wb+", SPOOL_MODE); ++ } + +- /* set expansion variable */ +- mime_decoded_filename = filename; ++/* set expansion variable */ ++mime_decoded_filename = filename; + +- return f; ++return f; + } + + +-int mime_decode(uschar **listptr) { +- int sep = 0; +- uschar *list = *listptr; +- uschar *option; +- uschar option_buffer[1024]; +- uschar decode_path[1024]; +- FILE *decode_file = NULL; +- long f_pos = 0; +- ssize_t size_counter = 0; +- ssize_t (*decode_function)(FILE*, FILE*, uschar*); +- +- if (mime_stream == NULL) ++int ++mime_decode(uschar **listptr) ++{ ++int sep = 0; ++uschar *list = *listptr; ++uschar *option; ++uschar option_buffer[1024]; ++uschar decode_path[1024]; ++FILE *decode_file = NULL; ++long f_pos = 0; ++ssize_t size_counter = 0; ++ssize_t (*decode_function)(FILE*, FILE*, uschar*); ++ ++if (mime_stream == NULL) ++ return FAIL; ++ ++f_pos = ftell(mime_stream); ++ ++/* build default decode path (will exist since MBOX must be spooled up) */ ++(void)string_format(decode_path,1024,"%s/scan/%s",spool_directory,message_id); ++ ++/* try to find 1st option */ ++if ((option = string_nextinlist(&list, &sep, ++ option_buffer, ++ sizeof(option_buffer))) != NULL) ++ { ++ /* parse 1st option */ ++ if ( (Ustrcmp(option,"false") == 0) || (Ustrcmp(option,"0") == 0) ) ++ /* explicitly no decoding */ + return FAIL; + +- f_pos = ftell(mime_stream); +- +- /* build default decode path (will exist since MBOX must be spooled up) */ +- (void)string_format(decode_path,1024,"%s/scan/%s",spool_directory,message_id); +- +- /* try to find 1st option */ +- if ((option = string_nextinlist(&list, &sep, +- option_buffer, +- sizeof(option_buffer))) != NULL) { ++ if (Ustrcmp(option,"default") == 0) ++ /* explicit default path + file names */ ++ goto DEFAULT_PATH; + +- /* parse 1st option */ +- if ( (Ustrcmp(option,"false") == 0) || (Ustrcmp(option,"0") == 0) ) { +- /* explicitly no decoding */ +- return FAIL; +- }; ++ if (option[0] == '/') ++ { ++ struct stat statbuf; + +- if (Ustrcmp(option,"default") == 0) { +- /* explicit default path + file names */ +- goto DEFAULT_PATH; +- }; ++ memset(&statbuf,0,sizeof(statbuf)); + +- if (option[0] == '/') { +- struct stat statbuf; +- +- memset(&statbuf,0,sizeof(statbuf)); +- +- /* assume either path or path+file name */ +- if ( (stat(CS option, &statbuf) == 0) && S_ISDIR(statbuf.st_mode) ) +- /* is directory, use it as decode_path */ +- decode_file = mime_get_decode_file(option, NULL); +- else +- /* does not exist or is a file, use as full file name */ +- decode_file = mime_get_decode_file(NULL, option); +- } ++ /* assume either path or path+file name */ ++ if ( (stat(CS option, &statbuf) == 0) && S_ISDIR(statbuf.st_mode) ) ++ /* is directory, use it as decode_path */ ++ decode_file = mime_get_decode_file(option, NULL); + else +- /* assume file name only, use default path */ +- decode_file = mime_get_decode_file(decode_path, option); +- } +- else +- /* no option? patch default path */ +- DEFAULT_PATH: decode_file = mime_get_decode_file(decode_path, NULL); +- +- if (decode_file == NULL) +- return DEFER; +- +- /* decode according to mime type */ +- if (mime_content_transfer_encoding == NULL) +- /* no encoding, dump as-is */ +- decode_function = mime_decode_asis; +- else if (Ustrcmp(mime_content_transfer_encoding, "base64") == 0) +- decode_function = mime_decode_base64; +- else if (Ustrcmp(mime_content_transfer_encoding, "quoted-printable") == 0) +- decode_function = mime_decode_qp; ++ /* does not exist or is a file, use as full file name */ ++ decode_file = mime_get_decode_file(NULL, option); ++ } + else +- /* unknown encoding type, just dump as-is */ +- decode_function = mime_decode_asis; ++ /* assume file name only, use default path */ ++ decode_file = mime_get_decode_file(decode_path, option); ++ } ++else ++ { ++ /* no option? patch default path */ ++DEFAULT_PATH: ++ decode_file = mime_get_decode_file(decode_path, NULL); ++ } + +- size_counter = decode_function(mime_stream, decode_file, mime_current_boundary); ++if (!decode_file) ++ return DEFER; + +- clearerr(mime_stream); +- fseek(mime_stream, f_pos, SEEK_SET); ++/* decode according to mime type */ ++decode_function = ++ !mime_content_transfer_encoding ++ ? mime_decode_asis /* no encoding, dump as-is */ ++ : Ustrcmp(mime_content_transfer_encoding, "base64") == 0 ++ ? mime_decode_base64 ++ : Ustrcmp(mime_content_transfer_encoding, "quoted-printable") == 0 ++ ? mime_decode_qp ++ : mime_decode_asis; /* unknown encoding type, just dump as-is */ + +- if (fclose(decode_file) != 0 || size_counter < 0) +- return DEFER; ++size_counter = decode_function(mime_stream, decode_file, mime_current_boundary); + +- /* round up to the next KiB */ +- mime_content_size = (size_counter + 1023) / 1024; ++clearerr(mime_stream); ++fseek(mime_stream, f_pos, SEEK_SET); + +- return OK; +-} ++if (fclose(decode_file) != 0 || size_counter < 0) ++ return DEFER; + +-int mime_get_header(FILE *f, uschar *header) { +- int c = EOF; +- int done = 0; +- int header_value_mode = 0; +- int header_open_brackets = 0; +- int num_copied = 0; ++/* round up to the next KiB */ ++mime_content_size = (size_counter + 1023) / 1024; + +- while(!done) { ++return OK; ++} + +- c = fgetc(f); +- if (c == EOF) break; ++int ++mime_get_header(FILE *f, uschar *header) ++{ ++int c = EOF; ++int done = 0; ++int header_value_mode = 0; ++int header_open_brackets = 0; ++int num_copied = 0; + +- /* always skip CRs */ +- if (c == '\r') continue; ++while(!done) ++ { ++ if ((c = fgetc(f)) == EOF) break; ++ ++ /* always skip CRs */ ++ if (c == '\r') continue; ++ ++ if (c == '\n') ++ { ++ if (num_copied > 0) ++ { ++ /* look if next char is '\t' or ' ' */ ++ if ((c = fgetc(f)) == EOF) break; ++ if ( (c == '\t') || (c == ' ') ) continue; ++ (void)ungetc(c,f); ++ } ++ /* end of the header, terminate with ';' */ ++ c = ';'; ++ done = 1; ++ } + +- if (c == '\n') { +- if (num_copied > 0) { +- /* look if next char is '\t' or ' ' */ +- c = fgetc(f); +- if (c == EOF) break; +- if ( (c == '\t') || (c == ' ') ) continue; +- (void)ungetc(c,f); +- }; +- /* end of the header, terminate with ';' */ +- c = ';'; +- done = 1; +- }; +- +- /* skip control characters */ +- if (c < 32) continue; +- +- if (header_value_mode) { +- /* --------- value mode ----------- */ +- /* skip leading whitespace */ +- if ( ((c == '\t') || (c == ' ')) && (header_value_mode == 1) ) +- continue; ++ /* skip control characters */ ++ if (c < 32) continue; ++ ++ if (header_value_mode) ++ { ++ /* --------- value mode ----------- */ ++ /* skip leading whitespace */ ++ if ( ((c == '\t') || (c == ' ')) && (header_value_mode == 1) ) ++ continue; + + /* we have hit a non-whitespace char, start copying value data */ + header_value_mode = 2; +@@ -400,295 +421,320 @@ int mime_get_header(FILE *f, uschar *header) { + }; + /* -------------------------------- */ + } +- else { +- /* -------- non-value mode -------- */ +- /* skip whitespace + tabs */ +- if ( (c == ' ') || (c == '\t') ) +- continue; +- if (c == '\\') { +- /* quote next char. can be used +- to escape brackets. */ +- c = fgetc(f); +- if (c == EOF) break; ++ else ++ { ++ /* -------- non-value mode -------- */ ++ /* skip whitespace + tabs */ ++ if ( (c == ' ') || (c == '\t') ) ++ continue; ++ if (c == '\\') ++ { ++ /* quote next char. can be used ++ to escape brackets. */ ++ if ((c = fgetc(f)) == EOF) break; + } +- else if (c == '(') { +- header_open_brackets++; +- continue; ++ else if (c == '(') ++ { ++ header_open_brackets++; ++ continue; + } +- else if ((c == ')') && header_open_brackets) { +- header_open_brackets--; +- continue; ++ else if ((c == ')') && header_open_brackets) ++ { ++ header_open_brackets--; ++ continue; + } +- else if ( (c == '=') && !header_open_brackets ) { +- /* enter value mode */ +- header_value_mode = 1; +- }; ++ else if ( (c == '=') && !header_open_brackets ) /* enter value mode */ ++ header_value_mode = 1; + +- /* skip chars while we are in a comment */ +- if (header_open_brackets > 0) +- continue; +- /* -------------------------------- */ +- }; ++ /* skip chars while we are in a comment */ ++ if (header_open_brackets > 0) ++ continue; ++ /* -------------------------------- */ ++ } + +- /* copy the char to the buffer */ +- header[num_copied] = (uschar)c; +- /* raise counter */ +- num_copied++; ++ /* copy the char to the buffer */ ++ header[num_copied++] = (uschar)c; + +- /* break if header buffer is full */ +- if (num_copied > MIME_MAX_HEADER_SIZE-1) { +- done = 1; +- }; +- }; ++ /* break if header buffer is full */ ++ if (num_copied > MIME_MAX_HEADER_SIZE-1) ++ done = 1; ++ } + +- if ((num_copied > 0) && (header[num_copied-1] != ';')) { +- header[num_copied-1] = ';'; +- }; ++if ((num_copied > 0) && (header[num_copied-1] != ';')) ++ header[num_copied-1] = ';'; + +- /* 0-terminate */ +- header[num_copied] = '\0'; ++/* 0-terminate */ ++header[num_copied] = '\0'; + +- /* return 0 for EOF or empty line */ +- if ((c == EOF) || (num_copied == 1)) +- return 0; +- else +- return 1; ++/* return 0 for EOF or empty line */ ++if ((c == EOF) || (num_copied == 1)) ++ return 0; ++else ++ return 1; + } + + +-int mime_acl_check(uschar *acl, FILE *f, struct mime_boundary_context *context, +- uschar **user_msgptr, uschar **log_msgptr) { +- int rc = OK; +- uschar *header = NULL; +- struct mime_boundary_context nested_context; +- +- /* reserve a line buffer to work in */ +- header = (uschar *)malloc(MIME_MAX_HEADER_SIZE+1); +- if (header == NULL) { +- log_write(0, LOG_PANIC, +- "MIME ACL: can't allocate %d bytes of memory.", MIME_MAX_HEADER_SIZE+1); +- return DEFER; +- }; +- +- /* Not actually used at the moment, but will be vital to fixing +- * some RFC 2046 nonconformance later... */ +- nested_context.parent = context; +- +- /* loop through parts */ +- while(1) { +- +- /* reset all per-part mime variables */ +- mime_anomaly_level = 0; +- mime_anomaly_text = NULL; +- mime_boundary = NULL; +- mime_charset = NULL; +- mime_decoded_filename = NULL; +- mime_filename = NULL; +- mime_content_description = NULL; +- mime_content_disposition = NULL; +- mime_content_id = NULL; +- mime_content_transfer_encoding = NULL; +- mime_content_type = NULL; +- mime_is_multipart = 0; +- mime_content_size = 0; +- +- /* +- If boundary is null, we assume that *f is positioned on the start of headers (for example, +- at the very beginning of a message. +- If a boundary is given, we must first advance to it to reach the start of the next header +- block. +- */ +- +- /* NOTE -- there's an error here -- RFC2046 specifically says to +- * check for outer boundaries. This code doesn't do that, and +- * I haven't fixed this. +- * +- * (I have moved partway towards adding support, however, by adding +- * a "parent" field to my new boundary-context structure.) +- */ +- if (context != NULL) { +- while(fgets(CS header, MIME_MAX_HEADER_SIZE, f) != NULL) { +- /* boundary line must start with 2 dashes */ +- if (Ustrncmp(header,"--",2) == 0) { +- if (Ustrncmp((header+2),context->boundary,Ustrlen(context->boundary)) == 0) { +- /* found boundary */ +- if (Ustrncmp((header+2+Ustrlen(context->boundary)),"--",2) == 0) { +- /* END boundary found */ +- debug_printf("End boundary found %s\n", context->boundary); +- return rc; +- } +- else { +- debug_printf("Next part with boundary %s\n", context->boundary); +- }; +- /* can't use break here */ +- goto DECODE_HEADERS; +- } +- }; ++int ++mime_acl_check(uschar *acl, FILE *f, struct mime_boundary_context *context, ++ uschar **user_msgptr, uschar **log_msgptr) ++{ ++int rc = OK; ++uschar *header = NULL; ++struct mime_boundary_context nested_context; ++ ++/* reserve a line buffer to work in */ ++if (!(header = (uschar *)malloc(MIME_MAX_HEADER_SIZE+1))) ++ { ++ log_write(0, LOG_PANIC, ++ "MIME ACL: can't allocate %d bytes of memory.", MIME_MAX_HEADER_SIZE+1); ++ return DEFER; ++ } ++ ++/* Not actually used at the moment, but will be vital to fixing ++ * some RFC 2046 nonconformance later... */ ++nested_context.parent = context; ++ ++/* loop through parts */ ++while(1) ++ { ++ /* reset all per-part mime variables */ ++ mime_anomaly_level = 0; ++ mime_anomaly_text = NULL; ++ mime_boundary = NULL; ++ mime_charset = NULL; ++ mime_decoded_filename = NULL; ++ mime_filename = NULL; ++ mime_content_description = NULL; ++ mime_content_disposition = NULL; ++ mime_content_id = NULL; ++ mime_content_transfer_encoding = NULL; ++ mime_content_type = NULL; ++ mime_is_multipart = 0; ++ mime_content_size = 0; ++ ++ /* ++ If boundary is null, we assume that *f is positioned on the start of headers (for example, ++ at the very beginning of a message. ++ If a boundary is given, we must first advance to it to reach the start of the next header ++ block. ++ */ ++ ++ /* NOTE -- there's an error here -- RFC2046 specifically says to ++ * check for outer boundaries. This code doesn't do that, and ++ * I haven't fixed this. ++ * ++ * (I have moved partway towards adding support, however, by adding ++ * a "parent" field to my new boundary-context structure.) ++ */ ++ if (context != NULL) ++ { ++ while(fgets(CS header, MIME_MAX_HEADER_SIZE, f) != NULL) ++ { ++ /* boundary line must start with 2 dashes */ ++ if (Ustrncmp(header,"--",2) == 0) ++ { ++ if (Ustrncmp((header+2),context->boundary,Ustrlen(context->boundary)) == 0) ++ { ++ /* found boundary */ ++ if (Ustrncmp((header+2+Ustrlen(context->boundary)),"--",2) == 0) ++ { ++ /* END boundary found */ ++ debug_printf("End boundary found %s\n", context->boundary); ++ return rc; ++ } ++ else ++ debug_printf("Next part with boundary %s\n", context->boundary); ++ ++ /* can't use break here */ ++ goto DECODE_HEADERS; ++ } ++ } + } +- /* Hit EOF or read error. Ugh. */ +- debug_printf("Hit EOF ...\n"); +- return rc; +- }; +- +- DECODE_HEADERS: +- /* parse headers, set up expansion variables */ +- while(mime_get_header(f,header)) { +- int i; +- /* loop through header list */ +- for (i = 0; i < mime_header_list_size; i++) { +- uschar *header_value = NULL; +- int header_value_len = 0; +- +- /* found an interesting header? */ +- if (strncmpic(mime_header_list[i].name,header,mime_header_list[i].namelen) == 0) { +- uschar *p = header + mime_header_list[i].namelen; +- /* yes, grab the value (normalize to lower case) +- and copy to its corresponding expansion variable */ +- while(*p != ';') { +- *p = tolower(*p); +- p++; +- }; +- header_value_len = (p - (header + mime_header_list[i].namelen)); +- header_value = (uschar *)malloc(header_value_len+1); +- memset(header_value,0,header_value_len+1); +- p = header + mime_header_list[i].namelen; +- Ustrncpy(header_value, p, header_value_len); +- debug_printf("Found %s MIME header, value is '%s'\n", mime_header_list[i].name, header_value); +- *((uschar **)(mime_header_list[i].value)) = header_value; +- +- /* make p point to the next character after the closing ';' */ +- p += (header_value_len+1); +- +- /* grab all param=value tags on the remaining line, check if they are interesting */ +- NEXT_PARAM_SEARCH: while (*p != 0) { +- int j; +- for (j = 0; j < mime_parameter_list_size; j++) { +- uschar *param_value = NULL; +- int param_value_len = 0; +- +- /* found an interesting parameter? */ +- if (strncmpic(mime_parameter_list[j].name,p,mime_parameter_list[j].namelen) == 0) { +- uschar *q = p + mime_parameter_list[j].namelen; +- /* yes, grab the value and copy to its corresponding expansion variable */ +- while (*q && *q != ';') +- { +- if (*q == '"') do q++; while (*q != '"'); +- q++; +- } +- +- param_value_len = (q - (p + mime_parameter_list[j].namelen)); +- param_value = (uschar *)malloc(param_value_len+1); +- memset(param_value,0,param_value_len+1); +- q = p + mime_parameter_list[j].namelen; +- Ustrncpy(param_value, q, param_value_len); +- param_value = rfc2047_decode(param_value, check_rfc2047_length, NULL, 32, ¶m_value_len, &q); +- debug_printf("Found %s MIME parameter in %s header, value is '%s'\n", mime_parameter_list[j].name, mime_header_list[i].name, param_value); +- *((uschar **)(mime_parameter_list[j].value)) = param_value; +- p += (mime_parameter_list[j].namelen + param_value_len + 1); +- goto NEXT_PARAM_SEARCH; +- }; +- } +- /* There is something, but not one of our interesting parameters. +- Advance to the next semicolon */ +- while(*p != ';') p++; +- p++; +- }; +- }; +- }; +- }; ++ /* Hit EOF or read error. Ugh. */ ++ debug_printf("Hit EOF ...\n"); ++ return rc; ++ } + +- /* set additional flag variables (easier access) */ +- if ( (mime_content_type != NULL) && +- (Ustrncmp(mime_content_type,"multipart",9) == 0) ) +- mime_is_multipart = 1; ++DECODE_HEADERS: ++ /* parse headers, set up expansion variables */ ++ while (mime_get_header(f,header)) ++ { ++ int i; ++ /* loop through header list */ ++ for (i = 0; i < mime_header_list_size; i++) ++ { ++ uschar *header_value = NULL; ++ int header_value_len = 0; ++ ++ /* found an interesting header? */ ++ if (strncmpic(mime_header_list[i].name,header,mime_header_list[i].namelen) == 0) ++ { ++ uschar *p = header + mime_header_list[i].namelen; ++ /* yes, grab the value (normalize to lower case) ++ and copy to its corresponding expansion variable */ ++ while(*p != ';') ++ { ++ *p = tolower(*p); ++ p++; ++ } ++ header_value_len = (p - (header + mime_header_list[i].namelen)); ++ header_value = (uschar *)malloc(header_value_len+1); ++ memset(header_value,0,header_value_len+1); ++ p = header + mime_header_list[i].namelen; ++ Ustrncpy(header_value, p, header_value_len); ++ debug_printf("Found %s MIME header, value is '%s'\n", mime_header_list[i].name, header_value); ++ *((uschar **)(mime_header_list[i].value)) = header_value; ++ ++ /* make p point to the next character after the closing ';' */ ++ p += (header_value_len+1); ++ ++ /* grab all param=value tags on the remaining line, check if they are interesting */ ++NEXT_PARAM_SEARCH: ++ while (*p != 0) ++ { ++ mime_parameter * mp; ++ for (mp = mime_parameter_list; ++ mp < &mime_parameter_list[mime_parameter_list_size]; ++ mp++) ++ { ++ uschar *param_value = NULL; ++ int param_value_len = 0; ++ ++ /* found an interesting parameter? */ ++ if (strncmpic(mp->name, p, mp->namelen) == 0) ++ { ++ uschar *q = p + mp->namelen; ++ int size = 0; ++ int ptr = 0; ++ ++ /* yes, grab the value and copy to its corresponding expansion variable */ ++ while(*q && *q != ';') /* ; terminates */ ++ { ++ if (*q == '"') ++ { ++ q++; /* skip leading " */ ++ while(*q && *q != '"') /* which protects ; */ ++ param_value = string_cat(param_value, &size, &ptr, q++, 1); ++ if (*q) q++; /* skip trailing " */ ++ } ++ else ++ param_value = string_cat(param_value, &size, &ptr, q++, 1); ++ } ++ param_value[ptr++] = '\0'; ++ param_value_len = ptr; ++ ++ param_value = rfc2047_decode(param_value, check_rfc2047_length, NULL, 32, ¶m_value_len, &q); ++ debug_printf("Found %s MIME parameter in %s header, value is '%s'\n", mp->name, mime_header_list[i].name, param_value); ++ *((uschar **)(mp->value)) = param_value; ++ p += (mp->namelen + param_value_len + 1); ++ goto NEXT_PARAM_SEARCH; ++ } ++ } ++ /* There is something, but not one of our interesting parameters. ++ Advance to the next semicolon */ ++ while(*p != ';') p++; ++ p++; ++ } ++ } ++ } ++ } + +- /* Make a copy of the boundary pointer. +- Required since mime_boundary is global +- and can be overwritten further down in recursion */ +- nested_context.boundary = mime_boundary; ++ /* set additional flag variables (easier access) */ ++ if ( (mime_content_type != NULL) && ++ (Ustrncmp(mime_content_type,"multipart",9) == 0) ) ++ mime_is_multipart = 1; + +- /* raise global counter */ +- mime_part_count++; ++ /* Make a copy of the boundary pointer. ++ Required since mime_boundary is global ++ and can be overwritten further down in recursion */ ++ nested_context.boundary = mime_boundary; + +- /* copy current file handle to global variable */ +- mime_stream = f; +- mime_current_boundary = context ? context->boundary : 0; ++ /* raise global counter */ ++ mime_part_count++; + +- /* Note the context */ +- mime_is_coverletter = !(context && context->context == MBC_ATTACHMENT); ++ /* copy current file handle to global variable */ ++ mime_stream = f; ++ mime_current_boundary = context ? context->boundary : 0; + +- /* call ACL handling function */ +- rc = acl_check(ACL_WHERE_MIME, NULL, acl, user_msgptr, log_msgptr); ++ /* Note the context */ ++ mime_is_coverletter = !(context && context->context == MBC_ATTACHMENT); + +- mime_stream = NULL; +- mime_current_boundary = NULL; ++ /* call ACL handling function */ ++ rc = acl_check(ACL_WHERE_MIME, NULL, acl, user_msgptr, log_msgptr); + +- if (rc != OK) break; ++ mime_stream = NULL; ++ mime_current_boundary = NULL; ++ ++ if (rc != OK) break; + +- /* If we have a multipart entity and a boundary, go recursive */ +- if ( (mime_content_type != NULL) && +- (nested_context.boundary != NULL) && +- (Ustrncmp(mime_content_type,"multipart",9) == 0) ) { +- debug_printf("Entering multipart recursion, boundary '%s'\n", nested_context.boundary); +- +- if (context && context->context == MBC_ATTACHMENT) +- nested_context.context = MBC_ATTACHMENT; +- else if (!Ustrcmp(mime_content_type,"multipart/alternative") +- || !Ustrcmp(mime_content_type,"multipart/related")) +- nested_context.context = MBC_COVERLETTER_ALL; +- else +- nested_context.context = MBC_COVERLETTER_ONESHOT; +- +- rc = mime_acl_check(acl, f, &nested_context, user_msgptr, log_msgptr); +- if (rc != OK) break; ++ /* If we have a multipart entity and a boundary, go recursive */ ++ if ( (mime_content_type != NULL) && ++ (nested_context.boundary != NULL) && ++ (Ustrncmp(mime_content_type,"multipart",9) == 0) ) ++ { ++ debug_printf("Entering multipart recursion, boundary '%s'\n", nested_context.boundary); ++ ++ nested_context.context = ++ context && context->context == MBC_ATTACHMENT ++ ? MBC_ATTACHMENT ++ : Ustrcmp(mime_content_type,"multipart/alternative") == 0 ++ || Ustrcmp(mime_content_type,"multipart/related") == 0 ++ ? MBC_COVERLETTER_ALL ++ : MBC_COVERLETTER_ONESHOT; ++ ++ rc = mime_acl_check(acl, f, &nested_context, user_msgptr, log_msgptr); ++ if (rc != OK) break; + } +- else if ( (mime_content_type != NULL) && +- (Ustrncmp(mime_content_type,"message/rfc822",14) == 0) ) { +- uschar *rfc822name = NULL; +- uschar filename[2048]; +- int file_nr = 0; +- int result = 0; +- +- /* must find first free sequential filename */ +- do { +- struct stat mystat; +- (void)string_format(filename,2048,"%s/scan/%s/__rfc822_%05u", spool_directory, message_id, file_nr); +- file_nr++; +- /* security break */ +- if (file_nr >= 128) +- goto NO_RFC822; +- result = stat(CS filename,&mystat); +- } +- while(result != -1); +- +- rfc822name = filename; +- +- /* decode RFC822 attachment */ +- mime_decoded_filename = NULL; +- mime_stream = f; +- mime_current_boundary = context ? context->boundary : NULL; +- mime_decode(&rfc822name); +- mime_stream = NULL; +- mime_current_boundary = NULL; +- if (mime_decoded_filename == NULL) { +- /* decoding failed */ +- log_write(0, LOG_MAIN, +- "mime_regex acl condition warning - could not decode RFC822 MIME part to file."); +- return DEFER; +- }; +- mime_decoded_filename = NULL; +- }; ++ else if ( (mime_content_type != NULL) && ++ (Ustrncmp(mime_content_type,"message/rfc822",14) == 0) ) ++ { ++ uschar *rfc822name = NULL; ++ uschar filename[2048]; ++ int file_nr = 0; ++ int result = 0; + +- NO_RFC822: +- /* If the boundary of this instance is NULL, we are finished here */ +- if (context == NULL) break; ++ /* must find first free sequential filename */ ++ do ++ { ++ struct stat mystat; ++ (void)string_format(filename, 2048, ++ "%s/scan/%s/__rfc822_%05u", spool_directory, message_id, file_nr++); ++ /* security break */ ++ if (file_nr >= 128) ++ goto NO_RFC822; ++ result = stat(CS filename,&mystat); ++ } while (result != -1); ++ ++ rfc822name = filename; ++ ++ /* decode RFC822 attachment */ ++ mime_decoded_filename = NULL; ++ mime_stream = f; ++ mime_current_boundary = context ? context->boundary : NULL; ++ mime_decode(&rfc822name); ++ mime_stream = NULL; ++ mime_current_boundary = NULL; ++ if (!mime_decoded_filename) /* decoding failed */ ++ { ++ log_write(0, LOG_MAIN, ++ "mime_regex acl condition warning - could not decode RFC822 MIME part to file."); ++ return DEFER; ++ } ++ mime_decoded_filename = NULL; ++ } + +- if (context->context == MBC_COVERLETTER_ONESHOT) +- context->context = MBC_ATTACHMENT; ++NO_RFC822: ++ /* If the boundary of this instance is NULL, we are finished here */ ++ if (context == NULL) break; + +- }; ++ if (context->context == MBC_COVERLETTER_ONESHOT) ++ context->context = MBC_ATTACHMENT; ++ } + +- return rc; ++return rc; + } + +-#endif ++#endif /*WITH_CONTENT_SCAN*/ ++ ++/* vi: sw ai sw=2 ++*/ diff --git a/mail/exim/options b/mail/exim/options index 71a2b03af182..edc8d9d6bf0c 100644 --- a/mail/exim/options +++ b/mail/exim/options @@ -50,7 +50,7 @@ OPTIONS_DEFAULT+= AUTH_CRAM_MD5 \ OPTIONS_RADIO_TLS= TLS GNUTLS TLS_DESC= TLS support -OPTIONS_RADIO_LS= SA_EXIM SO_1024 KAS +OPTIONS_RADIO_LS= SA_EXIM KAS LS_DESC= Local scan patch OPTIONS_RADIO_SRSR= SRS SRS_ALT SRSR_DESC= Sender Rewriting Scheme @@ -110,7 +110,6 @@ READLINE_DESC= Enable readline(3) library REDIS_DESC= Enable redis lookups (experimental) SASLAUTHD_DESC= Enable use of Cyrus SASL auth daemon SA_EXIM_DESC= Build with Spamassassin local scan -SO_1024_DESC= Build with Spamooborona-1024 local scan SPF_DESC= Enable Sender Policy Framework checking SQLITE_DESC= Enable SQLite lookups SRS_DESC= Enable Sender Rewriting Scheme diff --git a/mail/exim/pkg-plist b/mail/exim/pkg-plist index 26d60bbb361b..3b276b812c2b 100644 --- a/mail/exim/pkg-plist +++ b/mail/exim/pkg-plist @@ -54,11 +54,3 @@ %%EXIM%%@owner root %%EXIM%%@group wheel %%EXIM%%@exec install -d -o %%EXIM_USER%% -g %%EXIM_GROUP%% /%%LOGDIR%% -%%SO_1024%%@owner %%EXIM_USER%% -%%SO_1024%%@group %%EXIM_GROUP%% -%%SO_1024%%@cwd / -%%SO_1024%%@dirrmtry var/spool/spamooborona -%%SO_1024%%@cwd %%RESETPREFIX%% -%%SO_1024%%@owner root -%%SO_1024%%@group wheel -%%SO_1024%%@exec install -d -o %%EXIM_USER%% -g %%EXIM_GROUP%% /var/spool/spamooborona