Password containing backslashes need to have them doubled to have them properly interpreted by the imap server.
A password terminating with a blackslash used to trigger this error:
IMAP command 'LOGIN <user> <pass>' returned response (BAD) - Missing '"'
Signed-off-by: Nicolas Morey-Chaisemartin <redacted>
---
imap-send.c | 28 +++++++++++++++++++++++++++-
1 file changed, 27 insertions(+), 1 deletion(-)
diff --git a/imap-send.c b/imap-send.c
index b2d0b849b..7fde6ec96 100644
--- a/imap-send.c
+++ b/imap-send.c
@@ -926,6 +926,32 @@ static int auth_cram_md5(struct imap_store *ctx, struct imap_cmd *cmd, const cha
return 0;
}
+static char* imap_escape_password(const char *passwd)
+{
+ const unsigned passwd_len = strlen(passwd);
+ char *escaped = xmalloc(2 * passwd_len + 1);
+ const char *passwd_cur = passwd;
+ char *escaped_cur = escaped;
+
+ do {
+ char *next = strchr(passwd_cur, '\\');
+
+ if (!next) {
+ strcpy(escaped_cur, passwd_cur);
+ } else {
+ int len = next - passwd_cur + 1;
+
+ memcpy(escaped_cur, passwd_cur, len);
+ escaped_cur += len;
+ next++;
+ *(escaped_cur++) = '\\';
+ }
+ passwd_cur = next;
+ } while(passwd_cur);
+
+ return escaped;
+}
+
static struct imap_store *imap_open_store(struct imap_server_conf *srvc, char *folder)
{
struct credential cred = CREDENTIAL_INIT;@@ -1090,7 +1116,7 @@ static struct imap_store *imap_open_store(struct imap_server_conf *srvc, char *f
if (!srvc->user)
srvc->user = xstrdup(cred.username);
if (!srvc->pass)
- srvc->pass = xstrdup(cred.password);
+ srvc->pass = imap_escape_password(cred.password);
}
if (srvc->auth_method) {
On Fri, Aug 04, 2017 at 06:16:53PM +0200, Nicolas Morey-Chaisemartin wrote:
quoted hunk
static struct imap_store *imap_open_store(struct imap_server_conf *srvc, char *folder)
{
struct credential cred = CREDENTIAL_INIT;@@ -1090,7 +1116,7 @@ static struct imap_store *imap_open_store(struct imap_server_conf *srvc, char *f
if (!srvc->user)
srvc->user = xstrdup(cred.username);
if (!srvc->pass)
- srvc->pass = xstrdup(cred.password);
+ srvc->pass = imap_escape_password(cred.password);
}
if (srvc->auth_method) {
I'm not sure if this is correct. It looks like this username and
password are used by whatever authentication method we use, whether
that's LOGIN or CRAM-MD5. I don't think we'd want to encode the
password here before sending it through the CRAM-MD5 authenticator.
--
brian m. carlson / brian with sandals: Houston, Texas, US
https://www.crustytoothpaste.net/~bmc | My opinion only
OpenPGP: https://keybase.io/bk2204
On Fri, Aug 04, 2017 at 08:06:43PM +0000, brian m. carlson wrote:
On Fri, Aug 04, 2017 at 06:16:53PM +0200, Nicolas Morey-Chaisemartin wrote:
quoted
static struct imap_store *imap_open_store(struct imap_server_conf *srvc, char *folder)
{
struct credential cred = CREDENTIAL_INIT;@@ -1090,7 +1116,7 @@ static struct imap_store *imap_open_store(struct imap_server_conf *srvc, char *f
if (!srvc->user)
srvc->user = xstrdup(cred.username);
if (!srvc->pass)
- srvc->pass = xstrdup(cred.password);
+ srvc->pass = imap_escape_password(cred.password);
}
if (srvc->auth_method) {
I'm not sure if this is correct. It looks like this username and
password are used by whatever authentication method we use, whether
that's LOGIN or CRAM-MD5. I don't think we'd want to encode the
password here before sending it through the CRAM-MD5 authenticator.
Yeah. This is an on-the-wire encoding issue, and should happen as part
of forming the protocol string to send. So:
imap_exec(ctx, NULL, "LOGIN \"%s\" \"%s\"", srvc->user, srvc->pass)
is probably where it needs to happen.
It looks like this issue is present in a lot of other places, too. Just
a few lines below I see:
imap_exec(ctx, NULL, "CREATE \"%s\"", ctx->name)
As an aside, these are all potential injection vulnerabilities, too.
E.g., if I specify my folder as
foo"\n. DELETE "bar
then we'd issue an accidental deletion. I doubt it's a big deal in
practice, as it's not common to feed attacker-controlled strings to
imap-send. But we should probably fix it anyway.
The right interface is probably to teach imap_exec() to take a
NULL-terminated list of items (rather than a format string) and then
quote each one appropriately.
-Peff