Auth: handle socket read errors in Dovecot authenticator
[exim.git] / src / src / auths / dovecot.c
index 6378c16428240cf63a749c13087ac199fc6d479b..4628863e0cc09714f7cec16024d21b6989e595a0 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2004 Andrey Panin <pazke@donpac.ru>
- * Copyright (c) 2006-2016 The Exim Maintainers
+ * Copyright (c) 2006-2017 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
@@ -78,8 +78,8 @@ auth_dovecot_options_block auth_dovecot_option_defaults = {
 /* Dummy values */
 void auth_dovecot_init(auth_instance *ablock) {}
 int auth_dovecot_server(auth_instance *ablock, uschar *data) {return 0;}
-int auth_dovecot_client(auth_instance *ablock, smtp_inblock *inblock,
-  smtp_outblock *outblock, int timeout, uschar *buffer, int buffsize) {return 0;}
+int auth_dovecot_client(auth_instance *ablock, void * sx,
+  int timeout, uschar *buffer, int buffsize) {return 0;}
 
 #else   /*!MACRO_PREDEF*/
 
@@ -131,52 +131,55 @@ actual fields (so last valid offset into ptrs is one less).
 static int
 strcut(uschar *str, uschar **ptrs, int nptrs)
 {
-       uschar *last_sub_start = str;
-       int n;
-
-       for (n = 0; n < nptrs; n++)
-               ptrs[n] = NULL;
-       n = 1;
-
-       while (*str) {
-               if (*str == '\t') {
-                       if (n <= nptrs) {
-                               *ptrs++ = last_sub_start;
-                               last_sub_start = str + 1;
-                               *str = '\0';
-                       }
-                       n++;
-               }
-               str++;
-       }
-
-       /* 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 {
-               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 *last_sub_start = str;
+int n;
+
+for (n = 0; n < nptrs; n++)
+  ptrs[n] = NULL;
+n = 1;
+
+while (*str)
+  {
+  if (*str == '\t')
+    {
+    if (n <= nptrs)
+      {
+      *ptrs++ = last_sub_start;
+      last_sub_start = str + 1;
+      *str = '\0';
+      }
+      n++;
+    }
+    str++;
+  }
+
+/* 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
+ {
+ 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;
 }
 
 static void debug_strcut(uschar **ptrs, int nlen, int alen) ARG_UNUSED;
 static void
 debug_strcut(uschar **ptrs, int nlen, int alen)
 {
-        int i;
-        debug_printf("%d read but unreturned bytes; strcut() gave %d results: ",
-                        socket_buffer_left, nlen);
-        for (i = 0; i < nlen; i++) {
-                debug_printf(" {%s}", ptrs[i]);
-        }
-        if (nlen < alen)
-                debug_printf(" last is %s\n", ptrs[i] ? ptrs[i] : US"<null>");
-        else
-                debug_printf(" (max for capacity)\n");
+int i;
+debug_printf("%d read but unreturned bytes; strcut() gave %d results: ",
+               socket_buffer_left, nlen);
+for (i = 0; i < nlen; i++)
+  debug_printf(" {%s}", ptrs[i]);
+if (nlen < alen)
+  debug_printf(" last is %s\n", ptrs[i] ? ptrs[i] : US"<null>");
+else
+  debug_printf(" (max for capacity)\n");
 }
 
 #define CHECK_COMMAND(str, arg_min, arg_max) do { \
@@ -212,8 +215,8 @@ for (;;)
   {
   if (socket_buffer_left == 0)
     {
-    socket_buffer_left = read(fd, sbuffer, sizeof(sbuffer));
-    if (socket_buffer_left == 0) { if (count == 0) return NULL; else break; }
+    if ((socket_buffer_left = read(fd, sbuffer, sizeof(sbuffer))) <= 0)
+      if (count == 0) return NULL; else break;
     p = 0;
     }
 
@@ -393,7 +396,7 @@ fprintf(f, "VERSION\t%d\t%d\r\nSERVICE\tSMTP\r\nCPID\t%d\r\n"
        "AUTH\t%d\t%s\trip=%s\tlip=%s\tresp=%s\r\n",
        VERSION_MAJOR, VERSION_MINOR, getpid(), cuid,
        ablock->public_name, sender_host_address, interface_address,
-       data ? (char *) data : "");
+       data ? CS  data : "");
 
 Subsequently, the command was modified to add "secured" and "valid-client-
 cert" when relevant.