]>
Commit | Line | Data |
---|---|---|
0a6eb0ab AM |
1 | ;+JH/01 Bug 2999: Fix a possible OOB write in the external authenticator, which |
2 | ; could be triggered by externally-supplied input. Found by Trend Micro. | |
3 | ; CVE-2023-42115 | |
4 | ; | |
5 | ;JH/02 Bug 3000: Fix a possible OOB write in the SPA authenticator, which could | |
6 | ; be triggered by externally-controlled input. Found by Trend Micro. | |
7 | ; CVE-2023-42116 | |
8 | ; | |
9 | ;JH/03 Bug 3001: Fix a possible OOB read in the SPA authenticator, which could | |
10 | ; be triggered by externally-controlled input. Found by Trend Micro. | |
11 | ; CVE-2023-42114 | |
12 | ; | |
13 | diff --git a/src/src/auths/auth-spa.c b/src/src/auths/auth-spa.c | |
14 | index 8d886b6b6..bb3d327d1 100644 | |
15 | --- a/src/src/auths/auth-spa.c | |
16 | +++ b/src/src/auths/auth-spa.c | |
17 | @@ -155,6 +155,9 @@ int main (int argc, char ** argv) | |
18 | up with a different answer to the one above) | |
19 | */ | |
20 | ||
21 | +#ifndef MACRO_PREDEF | |
22 | + | |
23 | + | |
24 | #define DEBUG_X(a,b) ; | |
25 | ||
26 | extern int DEBUGLEVEL; | |
27 | @@ -1211,7 +1214,9 @@ char versionString[] = "libntlm version 0.21"; | |
28 | ||
29 | #define spa_bytes_add(ptr, header, buf, count) \ | |
30 | { \ | |
31 | -if (buf && (count) != 0) /* we hate -Wint-in-bool-contex */ \ | |
32 | +if ( buf && (count) != 0 /* we hate -Wint-in-bool-contex */ \ | |
33 | + && ptr->bufIndex + count < sizeof(ptr->buffer) \ | |
34 | + ) \ | |
35 | { \ | |
36 | SSVAL(&ptr->header.len,0,count); \ | |
37 | SSVAL(&ptr->header.maxlen,0,count); \ | |
38 | @@ -1229,35 +1234,30 @@ else \ | |
39 | ||
40 | #define spa_string_add(ptr, header, string) \ | |
41 | { \ | |
42 | -char *p = string; \ | |
43 | +uschar * p = string; \ | |
44 | int len = 0; \ | |
45 | -if (p) len = strlen(p); \ | |
46 | -spa_bytes_add(ptr, header, (US p), len); \ | |
47 | +if (p) len = Ustrlen(p); \ | |
48 | +spa_bytes_add(ptr, header, p, len); \ | |
49 | } | |
50 | ||
51 | #define spa_unicode_add_string(ptr, header, string) \ | |
52 | { \ | |
53 | -char *p = string; \ | |
54 | -uschar *b = NULL; \ | |
55 | +uschar * p = string; \ | |
56 | +uschar * b = NULL; \ | |
57 | int len = 0; \ | |
58 | if (p) \ | |
59 | { \ | |
60 | - len = strlen(p); \ | |
61 | - b = strToUnicode(p); \ | |
62 | + len = Ustrlen(p); \ | |
63 | + b = US strToUnicode(CS p); \ | |
64 | } \ | |
65 | spa_bytes_add(ptr, header, b, len*2); \ | |
66 | } | |
67 | ||
68 | ||
69 | -#define GetUnicodeString(structPtr, header) \ | |
70 | -unicodeToString(((char*)structPtr) + IVAL(&structPtr->header.offset,0) , SVAL(&structPtr->header.len,0)/2) | |
71 | -#define GetString(structPtr, header) \ | |
72 | -toString(((CS structPtr) + IVAL(&structPtr->header.offset,0)), SVAL(&structPtr->header.len,0)) | |
73 | - | |
74 | #ifdef notdef | |
75 | ||
76 | #define DumpBuffer(fp, structPtr, header) \ | |
77 | -dumpRaw(fp,(US structPtr)+IVAL(&structPtr->header.offset,0),SVAL(&structPtr->header.len,0)) | |
78 | + dumpRaw(fp,(US structPtr)+IVAL(&structPtr->header.offset,0),SVAL(&structPtr->header.len,0)) | |
79 | ||
80 | ||
81 | static void | |
82 | @@ -1321,8 +1321,33 @@ buf[len] = 0; | |
83 | return buf; | |
84 | } | |
85 | ||
86 | +static inline uschar * | |
87 | +get_challenge_unistr(SPAAuthChallenge * challenge, SPAStrHeader * hdr) | |
88 | +{ | |
89 | +int off = IVAL(&hdr->offset, 0); | |
90 | +int len = SVAL(&hdr->len, 0); | |
91 | +return off + len < sizeof(SPAAuthChallenge) | |
92 | + ? US unicodeToString(CS challenge + off, len/2) : US""; | |
93 | +} | |
94 | + | |
95 | +static inline uschar * | |
96 | +get_challenge_str(SPAAuthChallenge * challenge, SPAStrHeader * hdr) | |
97 | +{ | |
98 | +int off = IVAL(&hdr->offset, 0); | |
99 | +int len = SVAL(&hdr->len, 0); | |
100 | +return off + len < sizeof(SPAAuthChallenge) | |
101 | + ? US toString(CS challenge + off, len) : US""; | |
102 | +} | |
103 | + | |
104 | #ifdef notdef | |
105 | ||
106 | +#define GetUnicodeString(structPtr, header) \ | |
107 | + unicodeToString(((char*)structPtr) + IVAL(&structPtr->header.offset,0) , SVAL(&structPtr->header.len,0)/2) | |
108 | + | |
109 | +#define GetString(structPtr, header) \ | |
110 | + toString(((CS structPtr) + IVAL(&structPtr->header.offset,0)), SVAL(&structPtr->header.len,0)) | |
111 | + | |
112 | + | |
113 | void | |
114 | dumpSmbNtlmAuthRequest (FILE * fp, SPAAuthRequest * request) | |
115 | { | |
116 | @@ -1366,15 +1391,15 @@ fprintf (fp, " Flags = %08x\n", IVAL (&response->flags, 0)); | |
117 | #endif | |
118 | ||
119 | void | |
120 | -spa_build_auth_request (SPAAuthRequest * request, char *user, char *domain) | |
121 | +spa_build_auth_request (SPAAuthRequest * request, uschar * user, uschar * domain) | |
122 | { | |
123 | -char *u = strdup (user); | |
124 | -char *p = strchr (u, '@'); | |
125 | +uschar * u = string_copy(user); | |
126 | +uschar * p = Ustrchr(u, '@'); | |
127 | ||
128 | if (p) | |
129 | { | |
130 | if (!domain) | |
131 | - domain = p + 1; | |
132 | + domain = p + 1; | |
133 | *p = '\0'; | |
134 | } | |
135 | ||
136 | @@ -1384,7 +1409,6 @@ SIVAL (&request->msgType, 0, 1); | |
137 | SIVAL (&request->flags, 0, 0x0000b207); /* have to figure out what these mean */ | |
138 | spa_string_add (request, user, u); | |
139 | spa_string_add (request, domain, domain); | |
140 | -free (u); | |
141 | } | |
142 | ||
143 | ||
144 | @@ -1475,16 +1499,16 @@ free (u); | |
145 | ||
146 | void | |
147 | spa_build_auth_response (SPAAuthChallenge * challenge, | |
148 | - SPAAuthResponse * response, char *user, | |
149 | - char *password) | |
150 | + SPAAuthResponse * response, uschar * user, | |
151 | + uschar * password) | |
152 | { | |
153 | uint8x lmRespData[24]; | |
154 | uint8x ntRespData[24]; | |
155 | uint32x cf = IVAL(&challenge->flags, 0); | |
156 | -char *u = strdup (user); | |
157 | -char *p = strchr (u, '@'); | |
158 | -char *d = NULL; | |
159 | -char *domain; | |
160 | +uschar * u = string_copy(user); | |
161 | +uschar * p = Ustrchr(u, '@'); | |
162 | +uschar * d = NULL; | |
163 | +uschar * domain; | |
164 | ||
165 | if (p) | |
166 | { | |
167 | @@ -1492,33 +1516,33 @@ if (p) | |
168 | *p = '\0'; | |
169 | } | |
170 | ||
171 | -else domain = d = strdup((cf & 0x1)? | |
172 | - CCS GetUnicodeString(challenge, uDomain) : | |
173 | - CCS GetString(challenge, uDomain)); | |
174 | +else domain = d = string_copy(cf & 0x1 | |
175 | + ? CUS get_challenge_unistr(challenge, &challenge->uDomain) | |
176 | + : CUS get_challenge_str(challenge, &challenge->uDomain)); | |
177 | ||
178 | -spa_smb_encrypt (US password, challenge->challengeData, lmRespData); | |
179 | -spa_smb_nt_encrypt (US password, challenge->challengeData, ntRespData); | |
180 | +spa_smb_encrypt(password, challenge->challengeData, lmRespData); | |
181 | +spa_smb_nt_encrypt(password, challenge->challengeData, ntRespData); | |
182 | ||
183 | response->bufIndex = 0; | |
184 | memcpy (response->ident, "NTLMSSP\0\0\0", 8); | |
185 | SIVAL (&response->msgType, 0, 3); | |
186 | ||
187 | -spa_bytes_add (response, lmResponse, lmRespData, (cf & 0x200) ? 24 : 0); | |
188 | -spa_bytes_add (response, ntResponse, ntRespData, (cf & 0x8000) ? 24 : 0); | |
189 | +spa_bytes_add(response, lmResponse, lmRespData, cf & 0x200 ? 24 : 0); | |
190 | +spa_bytes_add(response, ntResponse, ntRespData, cf & 0x8000 ? 24 : 0); | |
191 | ||
192 | if (cf & 0x1) { /* Unicode Text */ | |
193 | - spa_unicode_add_string (response, uDomain, domain); | |
194 | - spa_unicode_add_string (response, uUser, u); | |
195 | - spa_unicode_add_string (response, uWks, u); | |
196 | + spa_unicode_add_string(response, uDomain, domain); | |
197 | + spa_unicode_add_string(response, uUser, u); | |
198 | + spa_unicode_add_string(response, uWks, u); | |
199 | } else { /* OEM Text */ | |
200 | - spa_string_add (response, uDomain, domain); | |
201 | - spa_string_add (response, uUser, u); | |
202 | - spa_string_add (response, uWks, u); | |
203 | + spa_string_add(response, uDomain, domain); | |
204 | + spa_string_add(response, uUser, u); | |
205 | + spa_string_add(response, uWks, u); | |
206 | } | |
207 | ||
208 | -spa_string_add (response, sessionKey, NULL); | |
209 | +spa_string_add(response, sessionKey, NULL); | |
210 | response->flags = challenge->flags; | |
211 | - | |
212 | -if (d != NULL) free (d); | |
213 | -free (u); | |
214 | } | |
215 | + | |
216 | + | |
217 | +#endif /*!MACRO_PREDEF*/ | |
218 | diff --git a/src/src/auths/auth-spa.h b/src/src/auths/auth-spa.h | |
219 | index cfe1b086d..3b0b3a9e3 100644 | |
220 | --- a/src/src/auths/auth-spa.h | |
221 | +++ b/src/src/auths/auth-spa.h | |
222 | @@ -79,10 +79,10 @@ typedef struct | |
223 | ||
224 | void spa_bits_to_base64 (unsigned char *, const unsigned char *, int); | |
225 | int spa_base64_to_bits(char *, int, const char *); | |
226 | -void spa_build_auth_response (SPAAuthChallenge *challenge, | |
227 | - SPAAuthResponse *response, char *user, char *password); | |
228 | -void spa_build_auth_request (SPAAuthRequest *request, char *user, | |
229 | - char *domain); | |
230 | +void spa_build_auth_response (SPAAuthChallenge * challenge, | |
231 | + SPAAuthResponse * response, uschar * user, uschar * password); | |
232 | +void spa_build_auth_request (SPAAuthRequest * request, uschar * user, | |
233 | + uschar * domain); | |
234 | extern void spa_smb_encrypt (unsigned char * passwd, unsigned char * c8, | |
235 | unsigned char * p24); | |
236 | extern void spa_smb_nt_encrypt (unsigned char * passwd, unsigned char * c8, | |
237 | diff --git a/src/src/auths/external.c b/src/src/auths/external.c | |
238 | index 7e7fca841..790b98159 100644 | |
239 | --- a/src/src/auths/external.c | |
240 | +++ b/src/src/auths/external.c | |
241 | @@ -103,7 +103,7 @@ if (expand_nmax == 0) /* skip if rxd data */ | |
242 | if (ob->server_param2) | |
243 | { | |
244 | uschar * s = expand_string(ob->server_param2); | |
245 | - auth_vars[expand_nmax] = s; | |
246 | + auth_vars[expand_nmax = 1] = s; | |
247 | expand_nstring[++expand_nmax] = s; | |
248 | expand_nlength[expand_nmax] = Ustrlen(s); | |
249 | if (ob->server_param3) | |
250 | diff --git a/src/src/auths/spa.c b/src/src/auths/spa.c | |
251 | index ff90d33a3..bfaccefda 100644 | |
252 | --- a/src/src/auths/spa.c | |
253 | +++ b/src/src/auths/spa.c | |
254 | @@ -284,14 +284,13 @@ SPAAuthRequest request; | |
255 | SPAAuthChallenge challenge; | |
256 | SPAAuthResponse response; | |
257 | char msgbuf[2048]; | |
258 | -char *domain = NULL; | |
259 | -char *username, *password; | |
260 | +uschar * domain = NULL, * username, * password; | |
261 | ||
262 | /* Code added by PH to expand the options */ | |
263 | ||
264 | *buffer = 0; /* Default no message when cancelled */ | |
265 | ||
266 | -if (!(username = CS expand_string(ob->spa_username))) | |
267 | +if (!(username = expand_string(ob->spa_username))) | |
268 | { | |
269 | if (f.expand_string_forcedfail) return CANCELLED; | |
270 | string_format(buffer, buffsize, "expansion of \"%s\" failed in %s " | |
271 | @@ -300,7 +299,7 @@ if (!(username = CS expand_string(ob->spa_username))) | |
272 | return ERROR; | |
273 | } | |
274 | ||
275 | -if (!(password = CS expand_string(ob->spa_password))) | |
276 | +if (!(password = expand_string(ob->spa_password))) | |
277 | { | |
278 | if (f.expand_string_forcedfail) return CANCELLED; | |
279 | string_format(buffer, buffsize, "expansion of \"%s\" failed in %s " | |
280 | @@ -310,7 +309,7 @@ if (!(password = CS expand_string(ob->spa_password))) | |
281 | } | |
282 | ||
283 | if (ob->spa_domain) | |
284 | - if (!(domain = CS expand_string(ob->spa_domain))) | |
285 | + if (!(domain = expand_string(ob->spa_domain))) | |
286 | { | |
287 | if (f.expand_string_forcedfail) return CANCELLED; | |
288 | string_format(buffer, buffsize, "expansion of \"%s\" failed in %s " | |
289 | @@ -330,7 +329,7 @@ if (!smtp_read_response(sx, US buffer, buffsize, '3', timeout)) | |
290 | ||
291 | DSPA("\n\n%s authenticator: using domain %s\n\n", ablock->name, domain); | |
292 | ||
293 | -spa_build_auth_request(&request, CS username, domain); | |
294 | +spa_build_auth_request(&request, username, domain); | |
295 | spa_bits_to_base64(US msgbuf, US &request, spa_request_length(&request)); | |
296 | ||
297 | DSPA("\n\n%s authenticator: sending request (%s)\n\n", ablock->name, msgbuf); | |
298 | @@ -347,7 +346,7 @@ if (!smtp_read_response(sx, US buffer, buffsize, '3', timeout)) | |
299 | DSPA("\n\n%s authenticator: challenge (%s)\n\n", ablock->name, buffer + 4); | |
300 | spa_base64_to_bits(CS (&challenge), sizeof(challenge), CCS (buffer + 4)); | |
301 | ||
302 | -spa_build_auth_response(&challenge, &response, CS username, CS password); | |
303 | +spa_build_auth_response(&challenge, &response, username, password); | |
304 | spa_bits_to_base64(US msgbuf, US &response, spa_request_length(&response)); | |
305 | DSPA("\n\n%s authenticator: challenge response (%s)\n\n", ablock->name, msgbuf); | |
306 |