tidying
[exim.git] / src / src / auths / dovecot.c
index 032a089cad9876fe94dab4ca5e0877b01dadd4eb..c89411af8a4dbafa463c3d0c1875f750565d3e56 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * 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
@@ -118,7 +119,6 @@ static int
 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++)
@@ -137,16 +137,14 @@ strcut(uschar *str, uschar **ptrs, int nptrs)
                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;
@@ -242,7 +240,7 @@ int auth_dovecot_server(auth_instance *ablock, uschar *data)
        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");
 
@@ -302,8 +300,20 @@ int auth_dovecot_server(auth_instance *ablock, uschar *data)
                                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;