Commit 88c2fc77 88c2fc773ed17a22beebaabafc9c8ce8ecfc939d by Sergey Poznyakoff

Fix memory override in smtp.c code. Fix ESMTP capability parsing.

* mailbox/base64.c (mu_base64_encode): Make sure output buffer
is null-terminated.
* imap4d/auth_gss.c (auth_gssapi): Assume buffer returned
by mu_base64_encode is null-terminated.
* libproto/mailer/smtp.c (cram_md5): Take challenge_len
as argument. All callers updated.
(smtp_auth): Fix eventual memory override. Assume buffer returned
by mu_base64_encode is nul-terminated.
(smtp_parse_ehlo_ack): Fix capability parsing: (a) do not depend
on the continuation marker ('-' or ' ') and (b) fix parsing of
the SIZE capablity.
Move call to mu_rtrim_cset out of the internal loop.
1 parent 2235ee27
...@@ -192,7 +192,7 @@ auth_gssapi (struct imap4d_command *command, ...@@ -192,7 +192,7 @@ auth_gssapi (struct imap4d_command *command,
192 if (outbuf.length) 192 if (outbuf.length)
193 { 193 {
194 mu_base64_encode (outbuf.value, outbuf.length, &tmp, &size); 194 mu_base64_encode (outbuf.value, outbuf.length, &tmp, &size);
195 util_send ("+ %*.*s\r\n", size, size, tmp); 195 util_send ("+ %s\r\n", tmp);
196 free (tmp); 196 free (tmp);
197 gss_release_buffer (&min_stat, &outbuf); 197 gss_release_buffer (&min_stat, &outbuf);
198 } 198 }
...@@ -212,7 +212,7 @@ auth_gssapi (struct imap4d_command *command, ...@@ -212,7 +212,7 @@ auth_gssapi (struct imap4d_command *command,
212 if (outbuf.length) 212 if (outbuf.length)
213 { 213 {
214 mu_base64_encode (outbuf.value, outbuf.length, &tmp, &size); 214 mu_base64_encode (outbuf.value, outbuf.length, &tmp, &size);
215 util_send ("+ %*.*s\r\n", size, size, tmp); 215 util_send ("+ %s\r\n", tmp);
216 free (tmp); 216 free (tmp);
217 gss_release_buffer (&min_stat, &outbuf); 217 gss_release_buffer (&min_stat, &outbuf);
218 imap4d_getline (&token_str, &token_size, &token_len); 218 imap4d_getline (&token_str, &token_size, &token_len);
...@@ -232,7 +232,7 @@ auth_gssapi (struct imap4d_command *command, ...@@ -232,7 +232,7 @@ auth_gssapi (struct imap4d_command *command,
232 } 232 }
233 233
234 mu_base64_encode (outbuf.value, outbuf.length, &tmp, &size); 234 mu_base64_encode (outbuf.value, outbuf.length, &tmp, &size);
235 util_send ("+ %*.*s\r\n", size, size, tmp); 235 util_send ("+ %s\r\n", tmp);
236 free (tmp); 236 free (tmp);
237 237
238 imap4d_getline (&token_str, &token_size, &token_len); 238 imap4d_getline (&token_str, &token_size, &token_len);
......
...@@ -630,13 +630,13 @@ smtp_starttls (smtp_t smtp) ...@@ -630,13 +630,13 @@ smtp_starttls (smtp_t smtp)
630 } 630 }
631 631
632 static void 632 static void
633 cram_md5 (char *secret, unsigned char *challenge, unsigned char *digest) 633 cram_md5 (char *secret, unsigned char *challenge, size_t challenge_len,
634 unsigned char *digest)
634 { 635 {
635 struct mu_md5_ctx context; 636 struct mu_md5_ctx context;
636 unsigned char ipad[64]; 637 unsigned char ipad[64];
637 unsigned char opad[64]; 638 unsigned char opad[64];
638 int secret_len; 639 int secret_len;
639 int challenge_len;
640 int i; 640 int i;
641 641
642 if (secret == 0 || challenge == 0) 642 if (secret == 0 || challenge == 0)
...@@ -766,7 +766,7 @@ smtp_auth (smtp_t smtp) ...@@ -766,7 +766,7 @@ smtp_auth (smtp_t smtp)
766 mu_rtrim_cset (p, "\r\n"); 766 mu_rtrim_cset (p, "\r\n");
767 mu_base64_decode ((unsigned char*) p, strlen (p), &chl, &chlen); 767 mu_base64_decode ((unsigned char*) p, strlen (p), &chl, &chlen);
768 768
769 cram_md5 ((char *) mu_secret_password (secret), chl, digest); 769 cram_md5 ((char *) mu_secret_password (secret), chl, chlen, digest);
770 mu_secret_password_unref (secret); 770 mu_secret_password_unref (secret);
771 free (chl); 771 free (chl);
772 772
...@@ -776,7 +776,6 @@ smtp_auth (smtp_t smtp) ...@@ -776,7 +776,6 @@ smtp_auth (smtp_t smtp)
776 mu_asnprintf (&buf, &buflen, "%s %s", user, ascii_digest); 776 mu_asnprintf (&buf, &buflen, "%s %s", user, ascii_digest);
777 buflen = strlen (buf); 777 buflen = strlen (buf);
778 mu_base64_encode ((unsigned char*) buf, buflen, &b64buf, &b64buflen); 778 mu_base64_encode ((unsigned char*) buf, buflen, &b64buf, &b64buflen);
779 b64buf[b64buflen] = '\0';
780 free (buf); 779 free (buf);
781 780
782 status = smtp_writeline (smtp, "%s\r\n", b64buf); 781 status = smtp_writeline (smtp, "%s\r\n", b64buf);
...@@ -818,7 +817,6 @@ smtp_auth (smtp_t smtp) ...@@ -818,7 +817,6 @@ smtp_auth (smtp_t smtp)
818 buf[c] = '\0'; 817 buf[c] = '\0';
819 } 818 }
820 mu_base64_encode ((unsigned char*) buf, buflen, &b64buf, &b64buflen); 819 mu_base64_encode ((unsigned char*) buf, buflen, &b64buf, &b64buflen);
821 b64buf[b64buflen] = '\0';
822 free (buf); 820 free (buf);
823 821
824 status = smtp_writeline (smtp, "AUTH PLAIN %s\r\n", b64buf); 822 status = smtp_writeline (smtp, "AUTH PLAIN %s\r\n", b64buf);
...@@ -1398,42 +1396,43 @@ smtp_parse_ehlo_ack (smtp_t smtp) ...@@ -1398,42 +1396,43 @@ smtp_parse_ehlo_ack (smtp_t smtp)
1398 status = smtp_readline (smtp); 1396 status = smtp_readline (smtp);
1399 if ((smtp->ptr - smtp->buffer) > 4 && smtp->buffer[3] == '-') 1397 if ((smtp->ptr - smtp->buffer) > 4 && smtp->buffer[3] == '-')
1400 multi = 1; 1398 multi = 1;
1401 if (status == 0) 1399 if (status == 0 && memcmp (smtp->buffer, "250", 3) == 0)
1402 { 1400 {
1401 char *capa_str = smtp->buffer + 4;
1402
1403 smtp->ptr = smtp->buffer; 1403 smtp->ptr = smtp->buffer;
1404 1404
1405 if (!mu_c_strncasecmp (smtp->buffer, "250-STARTTLS", 12)) 1405 if (!mu_c_strncasecmp (capa_str, "STARTTLS", 8))
1406 smtp->capa |= CAPA_STARTTLS; 1406 smtp->capa |= CAPA_STARTTLS;
1407 else if (!mu_c_strncasecmp (smtp->buffer, "250-SIZE", 8)) 1407 else if (!mu_c_strncasecmp (capa_str, "SIZE", 4))
1408 { 1408 {
1409 char *p;
1410 size_t n;
1411
1409 smtp->capa |= CAPA_SIZE; 1412 smtp->capa |= CAPA_SIZE;
1410 if (smtp->buffer[8] == '=') 1413
1411 { 1414 n = strtoul (capa_str + 5, &p, 10);
1412 char *p; 1415 if (*p != '\n')
1413 size_t n = strtoul (smtp->buffer + 9, &p, 10); 1416 MU_DEBUG1 (smtp->mailer->debug, MU_DEBUG_ERROR,
1414 1417 "suspicious size capability: %s",
1415 if (*p != '\n') 1418 smtp->buffer);
1416 MU_DEBUG1 (smtp->mailer->debug, MU_DEBUG_ERROR, 1419 else
1417 "suspicious size declaration: %s", 1420 smtp->max_size = n;
1418 smtp->buffer);
1419 else
1420 smtp->max_size = n;
1421 }
1422 } 1421 }
1423 else if (!mu_c_strncasecmp (smtp->buffer, "250-AUTH", 8)) 1422 else if (!mu_c_strncasecmp (capa_str, "AUTH", 4))
1424 { 1423 {
1425 char *name, *s; 1424 char *name, *s;
1426 1425
1427 smtp->capa |= CAPA_AUTH; 1426 smtp->capa |= CAPA_AUTH;
1428 1427
1429 for (name = strtok_r (smtp->buffer + 8, " ", &s); name; 1428 for (name = strtok_r (capa_str + 5, " ", &s); name;
1430 name = strtok_r (NULL, " ", &s)) 1429 name = strtok_r (NULL, " ", &s))
1431 { 1430 {
1432 struct auth_mech_record *mechs = auth_mech_list; 1431 struct auth_mech_record *mechs = auth_mech_list;
1433 1432
1433 mu_rtrim_cset (name, "\r\n");
1434 for (; mechs->name; mechs++) 1434 for (; mechs->name; mechs++)
1435 { 1435 {
1436 mu_rtrim_cset (name, "\r\n");
1437 if (!mu_c_strcasecmp (mechs->name, name)) 1436 if (!mu_c_strcasecmp (mechs->name, name))
1438 { 1437 {
1439 smtp->auth_mechs |= mechs->id; 1438 smtp->auth_mechs |= mechs->id;
......
...@@ -26,11 +26,11 @@ ...@@ -26,11 +26,11 @@
26 26
27 int 27 int
28 mu_base64_encode (const unsigned char *input, size_t input_len, 28 mu_base64_encode (const unsigned char *input, size_t input_len,
29 unsigned char **output, size_t * output_len) 29 unsigned char **output, size_t *output_len)
30 { 30 {
31 static char b64tab[] = 31 static char b64tab[] =
32 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 32 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
33 size_t olen = 4 * (input_len + 2) / 3; 33 size_t olen = 4 * (input_len + 2) / 3 + 1;
34 unsigned char *out = malloc (olen); 34 unsigned char *out = malloc (olen);
35 35
36 if (!out) 36 if (!out)
...@@ -42,7 +42,6 @@ mu_base64_encode (const unsigned char *input, size_t input_len, ...@@ -42,7 +42,6 @@ mu_base64_encode (const unsigned char *input, size_t input_len,
42 *out++ = b64tab[((input[0] << 4) & 0x30) | (input[1] >> 4)]; 42 *out++ = b64tab[((input[0] << 4) & 0x30) | (input[1] >> 4)];
43 *out++ = b64tab[((input[1] << 2) & 0x3c) | (input[2] >> 6)]; 43 *out++ = b64tab[((input[1] << 2) & 0x3c) | (input[2] >> 6)];
44 *out++ = b64tab[input[2] & 0x3f]; 44 *out++ = b64tab[input[2] & 0x3f];
45 olen -= 4;
46 input_len -= 3; 45 input_len -= 3;
47 input += 3; 46 input += 3;
48 } 47 }
...@@ -58,12 +57,13 @@ mu_base64_encode (const unsigned char *input, size_t input_len, ...@@ -58,12 +57,13 @@ mu_base64_encode (const unsigned char *input, size_t input_len,
58 *out++ = '='; 57 *out++ = '=';
59 } 58 }
60 *output_len = out - *output; 59 *output_len = out - *output;
60 *out = 0;
61 return 0; 61 return 0;
62 } 62 }
63 63
64 int 64 int
65 mu_base64_decode (const unsigned char *input, size_t input_len, 65 mu_base64_decode (const unsigned char *input, size_t input_len,
66 unsigned char **output, size_t * output_len) 66 unsigned char **output, size_t *output_len)
67 { 67 {
68 static int b64val[128] = { 68 static int b64val[128] = {
69 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 69 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
......