Lines 171-180
Link Here
|
171 |
bool flag_expand = false; /* alias/virtusertable expansion */ |
171 |
bool flag_expand = false; /* alias/virtusertable expansion */ |
172 |
bool warnedmacro = false; /* have we logged that we couldn't fetch a macro? */ |
172 |
bool warnedmacro = false; /* have we logged that we couldn't fetch a macro? */ |
173 |
|
173 |
|
174 |
#if defined(__FreeBSD__) /* popen bug - see PR bin/50770 */ |
|
|
175 |
static pthread_mutex_t popen_mutex = PTHREAD_MUTEX_INITIALIZER; |
176 |
#endif |
177 |
|
178 |
// {{{ main() |
174 |
// {{{ main() |
179 |
|
175 |
|
180 |
int |
176 |
int |
Lines 461-519
Link Here
|
461 |
send another copy. The milter API will not let you send the |
457 |
send another copy. The milter API will not let you send the |
462 |
message AND return a failure code to the sender, so this is |
458 |
message AND return a failure code to the sender, so this is |
463 |
the only way to do it. */ |
459 |
the only way to do it. */ |
464 |
#if defined(__FreeBSD__) |
460 |
char *popen_argv[3]; |
465 |
int rv; |
|
|
466 |
#endif |
467 |
|
468 |
#if defined(HAVE_ASPRINTF) |
469 |
char *buf; |
470 |
#else |
471 |
char buf[1024]; |
472 |
#endif |
473 |
char *fmt="%s \"%s\""; |
474 |
FILE *p; |
461 |
FILE *p; |
475 |
|
462 |
|
476 |
#if defined(HAVE_ASPRINTF) |
463 |
popen_argv[0] = SENDMAIL; |
477 |
asprintf(&buf, fmt, SENDMAIL, spambucket); |
464 |
popen_argv[1] = spambucket; |
478 |
#else |
465 |
popen_argv[2] = NULL; |
479 |
#if defined(HAVE_SNPRINTF) |
466 |
|
480 |
snprintf(buf, sizeof(buf)-1, fmt, SENDMAIL, spambucket); |
467 |
debug(D_COPY, "calling %s %s", SENDMAIL, spambucket); |
481 |
#else |
468 |
p = popenv(popen_argv, "w"); |
482 |
/* XXX possible buffer overflow here */ |
|
|
483 |
sprintf(buf, fmt, SENDMAIL, spambucket); |
484 |
#endif |
485 |
#endif |
486 |
|
487 |
debug(D_COPY, "calling %s", buf); |
488 |
#if defined(__FreeBSD__) /* popen bug - see PR bin/50770 */ |
489 |
rv = pthread_mutex_lock(&popen_mutex); |
490 |
if (rv) |
491 |
{ |
492 |
debug(D_ALWAYS, "Could not lock popen mutex: %s", strerror(rv)); |
493 |
abort(); |
494 |
} |
495 |
#endif |
496 |
p = popen(buf, "w"); |
497 |
if (!p) |
469 |
if (!p) |
498 |
{ |
470 |
{ |
499 |
debug(D_COPY, "popen failed(%s). Will not send a copy to spambucket", strerror(errno)); |
471 |
debug(D_COPY, "popenv failed(%s). Will not send a copy to spambucket", strerror(errno)); |
500 |
} else |
472 |
} else |
501 |
{ |
473 |
{ |
502 |
// Send message provided by SpamAssassin |
474 |
// Send message provided by SpamAssassin |
503 |
fwrite(assassin->d().c_str(), assassin->d().size(), 1, p); |
475 |
fwrite(assassin->d().c_str(), assassin->d().size(), 1, p); |
504 |
pclose(p); p = NULL; |
476 |
fclose(p); p = NULL; |
505 |
} |
477 |
} |
506 |
#if defined(__FreeBSD__) |
|
|
507 |
rv = pthread_mutex_unlock(&popen_mutex); |
508 |
if (rv) |
509 |
{ |
510 |
debug(D_ALWAYS, "Could not unlock popen mutex: %s", strerror(rv)); |
511 |
abort(); |
512 |
} |
513 |
#endif |
514 |
#if defined(HAVE_ASPRINTF) |
515 |
free(buf); |
516 |
#endif |
517 |
} |
478 |
} |
518 |
return SMFIS_REJECT; |
479 |
return SMFIS_REJECT; |
519 |
} |
480 |
} |
Lines 842-871
Link Here
|
842 |
/* open a pipe to sendmail so we can do address expansion */ |
803 |
/* open a pipe to sendmail so we can do address expansion */ |
843 |
|
804 |
|
844 |
char buf[1024]; |
805 |
char buf[1024]; |
845 |
char *fmt="%s -bv \"%s\" 2>&1"; |
806 |
char *popen_argv[4]; |
846 |
|
807 |
|
847 |
#if defined(HAVE_SNPRINTF) |
808 |
popen_argv[0] = SENDMAIL; |
848 |
snprintf(buf, sizeof(buf)-1, fmt, SENDMAIL, envrcpt[0]); |
809 |
popen_argv[1] = "-bv"; |
849 |
#else |
810 |
popen_argv[2] = envrcpt[0]; |
850 |
/* XXX possible buffer overflow here */ |
811 |
popen_argv[3] = NULL; |
851 |
sprintf(buf, fmt, SENDMAIL, envrcpt[0]); |
|
|
852 |
#endif |
853 |
|
812 |
|
854 |
debug(D_RCPT, "calling %s", buf); |
813 |
debug(D_RCPT, "calling %s -bv %s", SENDMAIL, envrcpt[0]); |
855 |
|
814 |
|
856 |
#if defined(__FreeBSD__) /* popen bug - see PR bin/50770 */ |
815 |
p = popenv(popen_argv, "r"); |
857 |
rv = pthread_mutex_lock(&popen_mutex); |
|
|
858 |
if (rv) |
859 |
{ |
860 |
debug(D_ALWAYS, "Could not lock popen mutex: %s", strerror(rv)); |
861 |
abort(); |
862 |
} |
863 |
#endif |
864 |
|
865 |
p = popen(buf, "r"); |
866 |
if (!p) |
816 |
if (!p) |
867 |
{ |
817 |
{ |
868 |
debug(D_RCPT, "popen failed(%s). Will not expand aliases", strerror(errno)); |
818 |
debug(D_RCPT, "popenv failed(%s). Will not expand aliases", strerror(errno)); |
869 |
assassin->expandedrcpt.push_back(envrcpt[0]); |
819 |
assassin->expandedrcpt.push_back(envrcpt[0]); |
870 |
} else |
820 |
} else |
871 |
{ |
821 |
{ |
Lines 890-905
Link Here
|
890 |
assassin->expandedrcpt.push_back(p+7); |
840 |
assassin->expandedrcpt.push_back(p+7); |
891 |
} |
841 |
} |
892 |
} |
842 |
} |
893 |
pclose(p); p = NULL; |
843 |
fclose(p); p = NULL; |
894 |
} |
844 |
} |
895 |
#if defined(__FreeBSD__) |
|
|
896 |
rv = pthread_mutex_unlock(&popen_mutex); |
897 |
if (rv) |
898 |
{ |
899 |
debug(D_ALWAYS, "Could not unlock popen mutex: %s", strerror(rv)); |
900 |
abort(); |
901 |
} |
902 |
#endif |
903 |
} else |
845 |
} else |
904 |
{ |
846 |
{ |
905 |
assassin->expandedrcpt.push_back(envrcpt[0]); |
847 |
assassin->expandedrcpt.push_back(envrcpt[0]); |
Lines 2157-2161
Link Here
|
2157 |
warnedmacro = true; |
2099 |
warnedmacro = true; |
2158 |
} |
2100 |
} |
2159 |
|
2101 |
|
|
|
2102 |
/* |
2103 |
untrusted-argument-safe popen function - only supports "r" and "w" modes |
2104 |
for simplicity, and always reads stdout and stderr in "r" mode. Call |
2105 |
fclose to close the FILE. |
2106 |
*/ |
2107 |
FILE *popenv(char *const argv[], const char *type) |
2108 |
{ |
2109 |
FILE *iop; |
2110 |
int pdes[2]; |
2111 |
int save_errno; |
2112 |
if ((*type != 'r' && *type != 'w') || type[1]) |
2113 |
{ |
2114 |
errno = EINVAL; |
2115 |
return (NULL); |
2116 |
} |
2117 |
if (pipe(pdes) < 0) |
2118 |
return (NULL); |
2119 |
switch (fork()) { |
2120 |
|
2121 |
case -1: /* Error. */ |
2122 |
save_errno = errno; |
2123 |
(void)close(pdes[0]); |
2124 |
(void)close(pdes[1]); |
2125 |
errno = save_errno; |
2126 |
return (NULL); |
2127 |
/* NOTREACHED */ |
2128 |
case 0: /* Child. */ |
2129 |
if (*type == 'r') { |
2130 |
/* |
2131 |
* The dup2() to STDIN_FILENO is repeated to avoid |
2132 |
* writing to pdes[1], which might corrupt the |
2133 |
* parent's copy. This isn't good enough in |
2134 |
* general, since the exit() is no return, so |
2135 |
* the compiler is free to corrupt all the local |
2136 |
* variables. |
2137 |
*/ |
2138 |
(void)close(pdes[0]); |
2139 |
(void)dup2(pdes[1], STDOUT_FILENO); |
2140 |
(void)dup2(pdes[1], STDERR_FILENO); |
2141 |
if (pdes[1] != STDOUT_FILENO && pdes[1] != STDERR_FILENO) { |
2142 |
(void)close(pdes[1]); |
2143 |
} |
2144 |
} else { |
2145 |
if (pdes[0] != STDIN_FILENO) { |
2146 |
(void)dup2(pdes[0], STDIN_FILENO); |
2147 |
(void)close(pdes[0]); |
2148 |
} |
2149 |
(void)close(pdes[1]); |
2150 |
} |
2151 |
execv(argv[0], argv); |
2152 |
exit(127); |
2153 |
/* NOTREACHED */ |
2154 |
} |
2155 |
|
2156 |
/* Parent; assume fdopen can't fail. */ |
2157 |
if (*type == 'r') { |
2158 |
iop = fdopen(pdes[0], type); |
2159 |
(void)close(pdes[1]); |
2160 |
} else { |
2161 |
iop = fdopen(pdes[1], type); |
2162 |
(void)close(pdes[0]); |
2163 |
} |
2164 |
|
2165 |
return (iop); |
2166 |
} |
2167 |
|
2160 |
// }}} |
2168 |
// }}} |
2161 |
// vim6:ai:noexpandtab |
2169 |
// vim6:ai:noexpandtab |