There is a bug in current ssl_crtd code. The bug descriptions exists here:
  http://bugs.squid-cache.org/show_bug.cgi?id=3214
A patch fixing the bug uploaded here.

I am also posting the patch here, because it changes a little the helpers behaviour, so maybe a discussion required. This patch add the possibility to use other characters than the '\n' as the end of helper response mark.

Regards,
   Christos
Bug fix for "helperHandleRead: unexpected read from ssl_crtd" errors.

Squid would read the beginning of a crtd response split across multiple
read operations and treat it as a complete response, causing various
certificate-related errors.

This patch:
 - allow the use of other than the '\n' character as the end of message mark
   for helper responses.
 - Use the '\1' char as end-of-message char for crtd helper. This char looks 
   safe because the crtd messages are clear text only messages.

=== modified file 'src/helper.cc'
--- src/helper.cc	2011-03-16 12:03:03 +0000
+++ src/helper.cc	2011-05-04 14:36:12 +0000
@@ -881,30 +881,25 @@
         srv->rbuf[0] = '\0';
     }
 
-    if (hlp->return_full_reply) {
-        debugs(84, 3, HERE << "Return entire buffer");
-        helperReturnBuffer(0, srv, hlp, srv->rbuf, srv->rbuf + srv->roffset);
-    } else {
-        while ((t = strchr(srv->rbuf, '\n'))) {
-            /* end of reply found */
-            char *msg = srv->rbuf;
-            int i = 0;
-            debugs(84, 3, "helperHandleRead: end of reply found");
-
-            if (t > srv->rbuf && t[-1] == '\r')
-                t[-1] = '\0';
-
-            *t++ = '\0';
-
-            if (hlp->childs.concurrency) {
-                i = strtol(msg, &msg, 10);
-
-                while (*msg && xisspace(*msg))
-                    msg++;
-            }
-
-            helperReturnBuffer(i, srv, hlp, msg, t);
+    while ((t = strchr(srv->rbuf, hlp->eom))) {
+        /* end of reply found */
+        char *msg = srv->rbuf;
+        int i = 0;
+        debugs(84, 3, "helperHandleRead: end of reply found");
+        
+        if (t > srv->rbuf && t[-1] == '\r' && hlp->eom == '\n')
+            t[-1] = '\0';
+        
+        *t++ = '\0';
+        
+        if (hlp->childs.concurrency) {
+            i = strtol(msg, &msg, 10);
+            
+            while (*msg && xisspace(*msg))
+                msg++;
         }
+        
+        helperReturnBuffer(i, srv, hlp, msg, t);
     }
 
     if (srv->rfd != -1)
@@ -950,12 +945,12 @@
         srv->roffset = 0;
     }
 
-    if ((t = strchr(srv->rbuf, '\n'))) {
+    if ((t = strchr(srv->rbuf, hlp->eom))) {
         /* end of reply found */
         int called = 1;
         debugs(84, 3, "helperStatefulHandleRead: end of reply found");
 
-        if (t > srv->rbuf && t[-1] == '\r')
+        if (t > srv->rbuf && t[-1] == '\r' && hlp->eom == '\n')
             t[-1] = '\0';
 
         *t = '\0';

=== modified file 'src/helper.h'
--- src/helper.h	2010-11-18 08:01:53 +0000
+++ src/helper.h	2011-05-04 20:12:06 +0000
@@ -49,7 +49,7 @@
 class helper
 {
 public:
-    inline helper(const char *name) : cmdline(NULL), id_name(name) {};
+    inline helper(const char *name) : cmdline(NULL), id_name(name), eom('\n') {}
     ~helper();
 
 public:
@@ -62,6 +62,7 @@
     Ip::Address addr;
     time_t last_queue_warn;
     time_t last_restart;
+    char eom;   ///< The char which marks the end of (response) message, normally '\n'
 
     struct _stats {
         int requests;
@@ -69,8 +70,6 @@
         int queue_size;
         int avg_svc_time;
     } stats;
-    /// True if callback expects the whole helper output, as a c-string.
-    bool return_full_reply;
 
 private:
     CBDATA_CLASS2(helper);

=== modified file 'src/ssl/crtd_message.cc'
--- src/ssl/crtd_message.cc	2010-12-30 11:16:21 +0000
+++ src/ssl/crtd_message.cc	2011-05-04 16:36:19 +0000
@@ -126,7 +126,7 @@
     if (code.empty()) return std::string();
     char buffer[10];
     snprintf(buffer, sizeof(buffer), "%zd", body.length());
-    return code + ' ' + buffer + ' ' + body + '\n';
+    return code + ' ' + buffer + ' ' + body;
 }
 
 void Ssl::CrtdMessage::clear()

=== modified file 'src/ssl/helper.cc'
--- src/ssl/helper.cc	2010-11-18 08:01:53 +0000
+++ src/ssl/helper.cc	2011-05-04 16:35:10 +0000
@@ -30,6 +30,9 @@
         ssl_crtd = new helper("ssl_crtd");
     ssl_crtd->childs = Ssl::TheConfig.ssl_crtdChildren;
     ssl_crtd->ipc_type = IPC_STREAM;
+    // The crtd messages may contain the eol ('\n') character. We are
+    // going to use the '\1' char as the end-of-message mark.
+    ssl_crtd->eom = '\1';
     assert(ssl_crtd->cmdline == NULL);
     {
         char *tmp = xstrdup(Ssl::TheConfig.ssl_crtd);
@@ -57,7 +60,6 @@
         }
         safe_free(tmp_begin);
     }
-    ssl_crtd->return_full_reply = true;
     helperOpenServers(ssl_crtd);
 }
 
@@ -88,5 +90,7 @@
     }
 
     first_warn = 0;
-    helperSubmit(ssl_crtd, message.compose().c_str(), callback, data);
+    std::string msg = message.compose();
+    msg += '\n';
+    helperSubmit(ssl_crtd, msg.c_str(), callback, data);
 }

=== modified file 'src/ssl/ssl_crtd.cc'
--- src/ssl/ssl_crtd.cc	2010-11-18 08:01:53 +0000
+++ src/ssl/ssl_crtd.cc	2011-05-04 21:52:40 +0000
@@ -245,7 +245,8 @@
     response_message.setCode("ok");
     response_message.setBody(bufferToWrite);
 
-    std::cout << response_message.compose();
+    // Use the '\1' char as end-of-message character
+    std::cout << response_message.compose() << '\1' << std::flush;
 
     return true;
 }

Reply via email to