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; }