/*
* Copyright (c) 2004 Andrey Panin <pazke@donpac.ru>
+ * Copyright (c) 2006-2014 The Exim Maintainers
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
strcut(uschar *str, uschar **ptrs, int nptrs)
{
uschar *last_sub_start = str;
- uschar *lastvalid = str + Ustrlen(str);
int n;
for (n = 0; n < nptrs; n++)
str++;
}
- if (last_sub_start < lastvalid) {
- if (n <= nptrs) {
- *ptrs = last_sub_start;
- } else {
- HDEBUG(D_auth) debug_printf("dovecot: warning: too many results from tab-splitting; saw %d fields, room for %d\n", n, nptrs);
- n = nptrs;
- }
+ /* It's acceptable for the string to end with a tab character. We see
+ this in AUTH PLAIN without an initial response from the client, which
+ causing us to send "334 " and get the data from the client. */
+ if (n <= nptrs) {
+ *ptrs = last_sub_start;
} else {
- n--;
- HDEBUG(D_auth) debug_printf("dovecot: warning: ignoring trailing tab\n");
+ HDEBUG(D_auth) debug_printf("dovecot: warning: too many results from tab-splitting; saw %d fields, room for %d\n", n, nptrs);
+ n = nptrs;
}
return n <= nptrs ? n : nptrs;
uschar *p;
int nargs, tmp;
int crequid = 1, cont = 1, fd, ret = DEFER;
- BOOL found = FALSE;
+ BOOL found = FALSE, have_mech_line = FALSE;
HDEBUG(D_auth) debug_printf("dovecot authentication\n");
OUT("authentication socket protocol version mismatch");
} else if (Ustrcmp(args[0], US"MECH") == 0) {
CHECK_COMMAND("MECH", 1, INT_MAX);
+ have_mech_line = TRUE;
if (strcmpic(US args[1], ablock->public_name) == 0)
found = TRUE;
+ } else if (Ustrcmp(args[0], US"SPID") == 0) {
+ /* Unfortunately the auth protocol handshake wasn't designed well
+ to differentiate between auth-client/userdb/master. auth-userdb
+ and auth-master send VERSION + SPID lines only and nothing
+ afterwards, while auth-client sends VERSION + MECH + SPID +
+ CUID + more. The simplest way that we can determine if we've
+ connected to the correct socket is to see if MECH line exists or
+ not (alternatively we'd have to have a small timeout after SPID
+ to see if CUID is sent or not). */
+ if (!have_mech_line)
+ OUT("authentication socket type mismatch (connected to auth-master instead of auth-client)");
} else if (Ustrcmp(args[0], US"DONE") == 0) {
CHECK_COMMAND("DONE", 0, 0);
cont = 0;