popmaildir: fix several grave bugs with using memory past end of malloc block
diff --git a/mailutils/popmaildir.c b/mailutils/popmaildir.c
index d2cc7c0..1a72b87 100644
--- a/mailutils/popmaildir.c
+++ b/mailutils/popmaildir.c
@@ -16,12 +16,14 @@
{
const char *msg = command(fmt, param);
char *answer = xmalloc_fgetline(stdin);
- if (answer && '+' == *answer) {
+ if (answer && '+' == answer[0]) {
if (timeout)
alarm(0);
- if (ret)
- *ret = answer+4; // skip "+OK "
- else if (ENABLE_FEATURE_CLEAN_UP)
+ if (ret) {
+ // skip "+OK "
+ memmove(answer, answer + 4, strlen(answer) - 4);
+ *ret = answer;
+ } else
free(answer);
return;
}
@@ -94,31 +96,28 @@
// authenticate (if no -s given)
if (!(opts & OPT_s)) {
- // server supports APOP and we want it? -> use it
- if ('<' == *buf && (opts & OPT_a)) {
- md5_ctx_t md5;
- // yes! compose <stamp><password>
+ // server supports APOP and we want it?
+ if ('<' == buf[0] && (opts & OPT_a)) {
+ union { // save a bit of stack
+ md5_ctx_t ctx;
+ char hex[16 * 2 + 1];
+ } md5;
+ uint32_t res[16 / 4];
+
char *s = strchr(buf, '>');
if (s)
- strcpy(s+1, G.pass);
- s = buf;
- // get md5 sum of <stamp><password>
- md5_begin(&md5);
- md5_hash(s, strlen(s), &md5);
- md5_end(s, &md5);
- // NOTE: md5 struct contains enough space
- // so we reuse md5 space instead of xzalloc(16*2+1)
-#define md5_hex ((uint8_t *)&md5)
-// uint8_t *md5_hex = (uint8_t *)&md5;
- *bin2hex((char *)md5_hex, s, 16) = '\0';
+ s[1] = '\0';
+ // get md5 sum of "<stamp>password" string
+ md5_begin(&md5.ctx);
+ md5_hash(buf, strlen(buf), &md5.ctx);
+ md5_hash(G.pass, strlen(G.pass), &md5.ctx);
+ md5_end(res, &md5.ctx);
+ *bin2hex(md5.hex, (char*)res, 16) = '\0';
// APOP
- s = xasprintf("%s %s", G.user, md5_hex);
-#undef md5_hex
+ s = xasprintf("%s %s", G.user, md5.hex);
pop3_check("APOP %s", s);
- if (ENABLE_FEATURE_CLEAN_UP) {
- free(s);
- free(buf-4); // buf is "+OK " away from malloc'ed string
- }
+ free(s);
+ free(buf);
// server ignores APOP -> use simple text authentication
} else {
// USER
@@ -141,8 +140,7 @@
// if atoi fails to convert buf into number it returns 0
// in this case the following loop simply will not be executed
nmsg = atoi(buf);
- if (ENABLE_FEATURE_CLEAN_UP)
- free(buf-4); // buf is "+OK " away from malloc'ed string
+ free(buf);
// loop through messages
retr = (opts & OPT_T) ? xasprintf("TOP %%u %u", opt_nlines) : "RETR %u";