| @@ -1,13 +1,225 @@ | | | @@ -1,13 +1,225 @@ |
1 | $NetBSD: patch-aa,v 1.2 2006/10/12 12:19:09 obache Exp $ | | 1 | $NetBSD: patch-aa,v 1.2.32.1 2010/04/19 09:15:47 tron Exp $ |
| | | 2 | Added CVE-2010-1132 patch from: |
| | | 3 | https://bugzilla.redhat.com/attachment.cgi?id=401011 |
2 | | | 4 | |
3 | --- spamass-milter.cpp.orig 2006-03-23 21:41:36.000000000 +0000 | | 5 | --- spamass-milter.cpp.orig 2010-04-17 16:04:59.724786300 -0500 |
4 | +++ spamass-milter.cpp | | 6 | +++ spamass-milter.cpp 2010-04-17 16:05:04.755469800 -0500 |
5 | @@ -2033,7 +2033,7 @@ cmp_nocase_partial(const string& s, cons | | 7 | @@ -171,10 +171,6 @@ |
| | | 8 | bool flag_expand = false; /* alias/virtusertable expansion */ |
| | | 9 | bool warnedmacro = false; /* have we logged that we couldn't fetch a macro? */ |
| | | 10 | |
| | | 11 | -#if defined(__FreeBSD__) /* popen bug - see PR bin/50770 */ |
| | | 12 | -static pthread_mutex_t popen_mutex = PTHREAD_MUTEX_INITIALIZER; |
| | | 13 | -#endif |
| | | 14 | - |
| | | 15 | // {{{ main() |
| | | 16 | |
| | | 17 | int |
| | | 18 | @@ -461,59 +457,24 @@ |
| | | 19 | send another copy. The milter API will not let you send the |
| | | 20 | message AND return a failure code to the sender, so this is |
| | | 21 | the only way to do it. */ |
| | | 22 | -#if defined(__FreeBSD__) |
| | | 23 | - int rv; |
| | | 24 | -#endif |
| | | 25 | - |
| | | 26 | -#if defined(HAVE_ASPRINTF) |
| | | 27 | - char *buf; |
| | | 28 | -#else |
| | | 29 | - char buf[1024]; |
| | | 30 | -#endif |
| | | 31 | - char *fmt="%s \"%s\""; |
| | | 32 | + char *popen_argv[3]; |
| | | 33 | FILE *p; |
| | | 34 | |
| | | 35 | -#if defined(HAVE_ASPRINTF) |
| | | 36 | - asprintf(&buf, fmt, SENDMAIL, spambucket); |
| | | 37 | -#else |
| | | 38 | -#if defined(HAVE_SNPRINTF) |
| | | 39 | - snprintf(buf, sizeof(buf)-1, fmt, SENDMAIL, spambucket); |
| | | 40 | -#else |
| | | 41 | - /* XXX possible buffer overflow here */ |
| | | 42 | - sprintf(buf, fmt, SENDMAIL, spambucket); |
| | | 43 | -#endif |
| | | 44 | -#endif |
| | | 45 | - |
| | | 46 | - debug(D_COPY, "calling %s", buf); |
| | | 47 | -#if defined(__FreeBSD__) /* popen bug - see PR bin/50770 */ |
| | | 48 | - rv = pthread_mutex_lock(&popen_mutex); |
| | | 49 | - if (rv) |
| | | 50 | - { |
| | | 51 | - debug(D_ALWAYS, "Could not lock popen mutex: %s", strerror(rv)); |
| | | 52 | - abort(); |
| | | 53 | - } |
| | | 54 | -#endif |
| | | 55 | - p = popen(buf, "w"); |
| | | 56 | + popen_argv[0] = SENDMAIL; |
| | | 57 | + popen_argv[1] = spambucket; |
| | | 58 | + popen_argv[2] = NULL; |
| | | 59 | + |
| | | 60 | + debug(D_COPY, "calling %s %s", SENDMAIL, spambucket); |
| | | 61 | + p = popenv(popen_argv, "w"); |
| | | 62 | if (!p) |
| | | 63 | { |
| | | 64 | - debug(D_COPY, "popen failed(%s). Will not send a copy to spambucket", strerror(errno)); |
| | | 65 | + debug(D_COPY, "popenv failed(%s). Will not send a copy to spambucket", strerror(errno)); |
| | | 66 | } else |
| | | 67 | { |
| | | 68 | // Send message provided by SpamAssassin |
| | | 69 | fwrite(assassin->d().c_str(), assassin->d().size(), 1, p); |
| | | 70 | - pclose(p); p = NULL; |
| | | 71 | + fclose(p); p = NULL; |
| | | 72 | } |
| | | 73 | -#if defined(__FreeBSD__) |
| | | 74 | - rv = pthread_mutex_unlock(&popen_mutex); |
| | | 75 | - if (rv) |
| | | 76 | - { |
| | | 77 | - debug(D_ALWAYS, "Could not unlock popen mutex: %s", strerror(rv)); |
| | | 78 | - abort(); |
| | | 79 | - } |
| | | 80 | -#endif |
| | | 81 | -#if defined(HAVE_ASPRINTF) |
| | | 82 | - free(buf); |
| | | 83 | -#endif |
| | | 84 | } |
| | | 85 | return SMFIS_REJECT; |
| | | 86 | } |
| | | 87 | @@ -842,30 +803,19 @@ |
| | | 88 | /* open a pipe to sendmail so we can do address expansion */ |
| | | 89 | |
| | | 90 | char buf[1024]; |
| | | 91 | - char *fmt="%s -bv \"%s\" 2>&1"; |
| | | 92 | - |
| | | 93 | -#if defined(HAVE_SNPRINTF) |
| | | 94 | - snprintf(buf, sizeof(buf)-1, fmt, SENDMAIL, envrcpt[0]); |
| | | 95 | -#else |
| | | 96 | - /* XXX possible buffer overflow here */ |
| | | 97 | - sprintf(buf, fmt, SENDMAIL, envrcpt[0]); |
| | | 98 | -#endif |
| | | 99 | + char *popen_argv[4]; |
| | | 100 | + |
| | | 101 | + popen_argv[0] = SENDMAIL; |
| | | 102 | + popen_argv[1] = "-bv"; |
| | | 103 | + popen_argv[2] = envrcpt[0]; |
| | | 104 | + popen_argv[3] = NULL; |
| | | 105 | |
| | | 106 | - debug(D_RCPT, "calling %s", buf); |
| | | 107 | + debug(D_RCPT, "calling %s -bv %s", SENDMAIL, envrcpt[0]); |
| | | 108 | |
| | | 109 | -#if defined(__FreeBSD__) /* popen bug - see PR bin/50770 */ |
| | | 110 | - rv = pthread_mutex_lock(&popen_mutex); |
| | | 111 | - if (rv) |
| | | 112 | - { |
| | | 113 | - debug(D_ALWAYS, "Could not lock popen mutex: %s", strerror(rv)); |
| | | 114 | - abort(); |
| | | 115 | - } |
| | | 116 | -#endif |
| | | 117 | - |
| | | 118 | - p = popen(buf, "r"); |
| | | 119 | + p = popenv(popen_argv, "r"); |
| | | 120 | if (!p) |
| | | 121 | { |
| | | 122 | - debug(D_RCPT, "popen failed(%s). Will not expand aliases", strerror(errno)); |
| | | 123 | + debug(D_RCPT, "popenv failed(%s). Will not expand aliases", strerror(errno)); |
| | | 124 | assassin->expandedrcpt.push_back(envrcpt[0]); |
| | | 125 | } else |
| | | 126 | { |
| | | 127 | @@ -890,16 +840,8 @@ |
| | | 128 | assassin->expandedrcpt.push_back(p+7); |
| | | 129 | } |
| | | 130 | } |
| | | 131 | - pclose(p); p = NULL; |
| | | 132 | + fclose(p); p = NULL; |
| | | 133 | } |
| | | 134 | -#if defined(__FreeBSD__) |
| | | 135 | - rv = pthread_mutex_unlock(&popen_mutex); |
| | | 136 | - if (rv) |
| | | 137 | - { |
| | | 138 | - debug(D_ALWAYS, "Could not unlock popen mutex: %s", strerror(rv)); |
| | | 139 | - abort(); |
| | | 140 | - } |
| | | 141 | -#endif |
| | | 142 | } else |
| | | 143 | { |
| | | 144 | assassin->expandedrcpt.push_back(envrcpt[0]); |
| | | 145 | @@ -2033,7 +1975,7 @@ |
6 | string::const_iterator p=s.begin(); | | 146 | string::const_iterator p=s.begin(); |
7 | string::const_iterator p2=s2.begin(); | | 147 | string::const_iterator p2=s2.begin(); |
8 | | | 148 | |
9 | - while ( p != s.end() && p2 <= s2.end() ) { | | 149 | - while ( p != s.end() && p2 <= s2.end() ) { |
10 | + while ( p != s.end() ) { | | 150 | + while ( p != s.end() ) { |
11 | if (toupper(*p) != toupper(*p2)) | | 151 | if (toupper(*p) != toupper(*p2)) |
12 | { | | 152 | { |
13 | debug(D_STR, "c_nc_p: <%s><%s> : miss", s.c_str(), s2.c_str()); | | 153 | debug(D_STR, "c_nc_p: <%s><%s> : miss", s.c_str(), s2.c_str()); |
| | | 154 | @@ -2157,5 +2099,71 @@ |
| | | 155 | warnedmacro = true; |
| | | 156 | } |
| | | 157 | |
| | | 158 | +/* |
| | | 159 | + untrusted-argument-safe popen function - only supports "r" and "w" modes |
| | | 160 | + for simplicity, and always reads stdout and stderr in "r" mode. Call |
| | | 161 | + fclose to close the FILE. |
| | | 162 | +*/ |
| | | 163 | +FILE *popenv(char *const argv[], const char *type) |
| | | 164 | +{ |
| | | 165 | + FILE *iop; |
| | | 166 | + int pdes[2]; |
| | | 167 | + int save_errno; |
| | | 168 | + if ((*type != 'r' && *type != 'w') || type[1]) |
| | | 169 | + { |
| | | 170 | + errno = EINVAL; |
| | | 171 | + return (NULL); |
| | | 172 | + } |
| | | 173 | + if (pipe(pdes) < 0) |
| | | 174 | + return (NULL); |
| | | 175 | + switch (fork()) { |
| | | 176 | + |
| | | 177 | + case -1: /* Error. */ |
| | | 178 | + save_errno = errno; |
| | | 179 | + (void)close(pdes[0]); |
| | | 180 | + (void)close(pdes[1]); |
| | | 181 | + errno = save_errno; |
| | | 182 | + return (NULL); |
| | | 183 | + /* NOTREACHED */ |
| | | 184 | + case 0: /* Child. */ |
| | | 185 | + if (*type == 'r') { |
| | | 186 | + /* |
| | | 187 | + * The dup2() to STDIN_FILENO is repeated to avoid |
| | | 188 | + * writing to pdes[1], which might corrupt the |
| | | 189 | + * parent's copy. This isn't good enough in |
| | | 190 | + * general, since the exit() is no return, so |
| | | 191 | + * the compiler is free to corrupt all the local |
| | | 192 | + * variables. |
| | | 193 | + */ |
| | | 194 | + (void)close(pdes[0]); |
| | | 195 | + (void)dup2(pdes[1], STDOUT_FILENO); |
| | | 196 | + (void)dup2(pdes[1], STDERR_FILENO); |
| | | 197 | + if (pdes[1] != STDOUT_FILENO && pdes[1] != STDERR_FILENO) { |
| | | 198 | + (void)close(pdes[1]); |
| | | 199 | + } |
| | | 200 | + } else { |
| | | 201 | + if (pdes[0] != STDIN_FILENO) { |
| | | 202 | + (void)dup2(pdes[0], STDIN_FILENO); |
| | | 203 | + (void)close(pdes[0]); |
| | | 204 | + } |
| | | 205 | + (void)close(pdes[1]); |
| | | 206 | + } |
| | | 207 | + execv(argv[0], argv); |
| | | 208 | + exit(127); |
| | | 209 | + /* NOTREACHED */ |
| | | 210 | + } |
| | | 211 | + |
| | | 212 | + /* Parent; assume fdopen can't fail. */ |
| | | 213 | + if (*type == 'r') { |
| | | 214 | + iop = fdopen(pdes[0], type); |
| | | 215 | + (void)close(pdes[1]); |
| | | 216 | + } else { |
| | | 217 | + iop = fdopen(pdes[1], type); |
| | | 218 | + (void)close(pdes[0]); |
| | | 219 | + } |
| | | 220 | + |
| | | 221 | + return (iop); |
| | | 222 | +} |
| | | 223 | + |
| | | 224 | // }}} |
| | | 225 | // vim6:ai:noexpandtab |