helper.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2018 The Squid Software Foundation and contributors
3  *
4  * Squid software is distributed under GPLv2+ license and includes
5  * contributions from numerous individuals and organizations.
6  * Please see the COPYING and CONTRIBUTORS files for details.
7  */
8 
9 #include "squid.h"
10 #include "../helper.h"
11 #include "anyp/PortCfg.h"
12 #include "fs_io.h"
13 #include "helper/Reply.h"
14 #include "SquidConfig.h"
15 #include "SquidString.h"
16 #include "SquidTime.h"
18 #include "ssl/Config.h"
19 #include "ssl/helper.h"
20 #include "wordlist.h"
21 
23 
24 #if USE_SSL_CRTD
25 
26 namespace Ssl {
27 
30 public:
31  GeneratorRequestor(HLPCB *aCallback, void *aData): callback(aCallback), data(aData) {}
34 };
35 
39 
40 public:
42  void emplace(HLPCB *callback, void *data) { requestors.emplace_back(callback, data); }
43 
45 
47  typedef std::vector<GeneratorRequestor> GeneratorRequestors;
49 };
50 
52 typedef std::unordered_map<SBuf, GeneratorRequest*> GeneratorRequests;
53 
54 static void HandleGeneratorReply(void *data, const ::Helper::Reply &reply);
55 
56 } // namespace Ssl
57 
58 CBDATA_NAMESPACED_CLASS_INIT(Ssl, GeneratorRequest);
59 
61 static std::ostream &
62 operator <<(std::ostream &os, const Ssl::GeneratorRequest &gr)
63 {
64  return os << "crtGenRq" << gr.query.id.value << "/" << gr.requestors.size();
65 }
66 
69 
70 helper *Ssl::Helper::ssl_crtd = nullptr;
71 
73 {
74  assert(ssl_crtd == NULL);
75 
76  // we need to start ssl_crtd only if some port(s) need to bump SSL *and* generate certificates
77  // TODO: generate host certificates for SNI enabled accel ports
78  bool found = false;
79  for (AnyP::PortCfgPointer s = HttpPortList; !found && s != NULL; s = s->next)
80  found = s->flags.tunnelSslBumping && s->secure.generateHostCertificates;
81  if (!found)
82  return;
83 
85  ssl_crtd->childs.updateLimits(Ssl::TheConfig.ssl_crtdChildren);
86  ssl_crtd->ipc_type = IPC_STREAM;
87  // The crtd messages may contain the eol ('\n') character. We are
88  // going to use the '\1' char as the end-of-message mark.
89  ssl_crtd->eom = '\1';
90  assert(ssl_crtd->cmdline == NULL);
91  {
92  char *tmp = xstrdup(Ssl::TheConfig.ssl_crtd);
93  char *tmp_begin = tmp;
94  char *token = NULL;
95  while ((token = strwordtok(NULL, &tmp))) {
96  wordlistAdd(&ssl_crtd->cmdline, token);
97  }
98  safe_free(tmp_begin);
99  }
100  helperOpenServers(ssl_crtd);
101 }
102 
104 {
105  if (!ssl_crtd)
106  return;
107  helperShutdown(ssl_crtd);
108  wordlistDestroy(&ssl_crtd->cmdline);
109  delete ssl_crtd;
110  ssl_crtd = NULL;
111 }
112 
113 void
115 {
116  Shutdown();
117  Init();
118 }
119 
120 void Ssl::Helper::Submit(CrtdMessage const & message, HLPCB * callback, void * data)
121 {
122  SBuf rawMessage(message.compose().c_str()); // XXX: helpers cannot use SBuf
123  rawMessage.append("\n", 1);
124 
125  const auto pending = TheGeneratorRequests.find(rawMessage);
126  if (pending != TheGeneratorRequests.end()) {
127  pending->second->emplace(callback, data);
128  debugs(83, 5, "collapsed request from " << data << " onto " << *pending->second);
129  return;
130  }
131 
133  request->query = rawMessage;
134  request->emplace(callback, data);
135  TheGeneratorRequests.emplace(request->query, request);
136  debugs(83, 5, "request from " << data << " as " << *request);
137  // ssl_crtd becomes nil if Squid is reconfigured without SslBump or
138  // certificate generation disabled in the new configuration
139  if (ssl_crtd && ssl_crtd->trySubmit(request->query.c_str(), HandleGeneratorReply, request))
140  return;
141 
143  failReply.notes.add("message", "error 45 Temporary network problem, please retry later");
144  HandleGeneratorReply(request, failReply);
145 }
146 
148 static void
149 Ssl::HandleGeneratorReply(void *data, const ::Helper::Reply &reply)
150 {
151  const std::unique_ptr<Ssl::GeneratorRequest> request(static_cast<Ssl::GeneratorRequest*>(data));
152  assert(request);
153  const auto erased = TheGeneratorRequests.erase(request->query);
154  assert(erased);
155 
156  for (auto &requestor: request->requestors) {
157  if (void *cbdata = requestor.data.validDone()) {
158  debugs(83, 5, "to " << cbdata << " in " << *request);
159  requestor.callback(cbdata, reply);
160  }
161  }
162 }
163 #endif //USE_SSL_CRTD
164 
166 
168 {
169  if (!Ssl::TheConfig.ssl_crt_validator)
170  return;
171 
172  assert(ssl_crt_validator == NULL);
173 
174  // we need to start ssl_crtd only if some port(s) need to bump SSL
175  bool found = false;
176  for (AnyP::PortCfgPointer s = HttpPortList; !found && s != NULL; s = s->next)
177  found = s->flags.tunnelSslBumping;
178  if (!found)
179  return;
180 
181  ssl_crt_validator = new helper("ssl_crt_validator");
182  ssl_crt_validator->childs.updateLimits(Ssl::TheConfig.ssl_crt_validator_Children);
183  ssl_crt_validator->ipc_type = IPC_STREAM;
184  // The crtd messages may contain the eol ('\n') character. We are
185  // going to use the '\1' char as the end-of-message mark.
186  ssl_crt_validator->eom = '\1';
187  assert(ssl_crt_validator->cmdline == NULL);
188 
189  int ttl = 60;
190  size_t cache = 2048;
191  {
192  char *tmp = xstrdup(Ssl::TheConfig.ssl_crt_validator);
193  char *tmp_begin = tmp;
194  char * token = NULL;
195  bool parseParams = true;
196  while ((token = strwordtok(NULL, &tmp))) {
197  if (parseParams) {
198  if (strncmp(token, "ttl=", 4) == 0) {
199  ttl = atoi(token + 4);
200  continue;
201  } else if (strncmp(token, "cache=", 6) == 0) {
202  cache = atoi(token + 6);
203  continue;
204  } else
205  parseParams = false;
206  }
207  wordlistAdd(&ssl_crt_validator->cmdline, token);
208  }
209  xfree(tmp_begin);
210  }
211  helperOpenServers(ssl_crt_validator);
212 
213  //WARNING: initializing static member in an object initialization method
214  assert(HelperCache == NULL);
215  HelperCache = new Ssl::CertValidationHelper::LruCache(ttl, cache);
216 }
217 
219 {
220  if (!ssl_crt_validator)
221  return;
222  helperShutdown(ssl_crt_validator);
223  wordlistDestroy(&ssl_crt_validator->cmdline);
224  delete ssl_crt_validator;
225  ssl_crt_validator = NULL;
226 
227  // CertValidationHelper::HelperCache is a static member, it is not good policy to
228  // reset it here. Will work because the current Ssl::CertValidationHelper is
229  // always the same static object.
230  delete HelperCache;
231  HelperCache = NULL;
232 }
233 
234 void
236 {
237  Shutdown();
238  Init();
239 }
240 
242 {
244 
245 public:
246  SBuf query;
249 };
251 
252 static void
253 sslCrtvdHandleReplyWrapper(void *data, const ::Helper::Reply &reply)
254 {
256  std::string error;
257 
258  submitData *crtdvdData = static_cast<submitData *>(data);
259  assert(crtdvdData->ssl.get());
260  Ssl::CertValidationResponse::Pointer validationResponse = new Ssl::CertValidationResponse(crtdvdData->ssl);
261  if (reply.result == ::Helper::BrokenHelper) {
262  debugs(83, DBG_IMPORTANT, "\"ssl_crtvd\" helper error response: " << reply.other().content());
263  validationResponse->resultCode = ::Helper::BrokenHelper;
264  } else if (!reply.other().hasContent()) {
265  debugs(83, DBG_IMPORTANT, "\"ssl_crtvd\" helper returned NULL response");
266  validationResponse->resultCode = ::Helper::BrokenHelper;
267  } else if (replyMsg.parse(reply.other().content(), reply.other().contentSize()) != Ssl::CrtdMessage::OK ||
268  !replyMsg.parseResponse(*validationResponse, error) ) {
269  debugs(83, DBG_IMPORTANT, "WARNING: Reply from ssl_crtvd for " << " is incorrect");
270  debugs(83, DBG_IMPORTANT, "Certificate cannot be validated. ssl_crtvd response: " << replyMsg.getBody());
271  validationResponse->resultCode = ::Helper::BrokenHelper;
272  } else
273  validationResponse->resultCode = reply.result;
274 
276  Must(dialer);
277  dialer->arg1 = validationResponse;
278  ScheduleCallHere(crtdvdData->callback);
279 
280  if (Ssl::CertValidationHelper::HelperCache &&
281  (validationResponse->resultCode == ::Helper::Okay || validationResponse->resultCode == ::Helper::Error)) {
283  if (!Ssl::CertValidationHelper::HelperCache->add(crtdvdData->query, item))
284  delete item;
285  }
286 
287  delete crtdvdData;
288 }
289 
291 {
294  message.composeRequest(request);
295  debugs(83, 5, "SSL crtvd request: " << message.compose().c_str());
296 
297  submitData *crtdvdData = new submitData;
298  crtdvdData->query.assign(message.compose().c_str());
299  crtdvdData->query.append('\n');
300  crtdvdData->callback = callback;
301  crtdvdData->ssl = request.ssl;
302  Ssl::CertValidationResponse::Pointer const*validationResponse;
303 
305  (validationResponse = CertValidationHelper::HelperCache->get(crtdvdData->query))) {
306 
307  CertValidationHelper::CbDialer *dialer = dynamic_cast<CertValidationHelper::CbDialer*>(callback->getDialer());
308  Must(dialer);
309  dialer->arg1 = *validationResponse;
310  ScheduleCallHere(callback);
311  delete crtdvdData;
312  return;
313  }
314 
315  // ssl_crt_validator becomes nil if Squid is reconfigured with cert
316  // validator disabled in the new configuration
317  if (ssl_crt_validator && ssl_crt_validator->trySubmit(crtdvdData->query.c_str(), sslCrtvdHandleReplyWrapper, crtdvdData))
318  return;
319 
321  resp->resultCode = ::Helper::BrokenHelper;
323  Must(dialer);
324  dialer->arg1 = resp;
325  ScheduleCallHere(callback);
326  delete crtdvdData;
327  return;
328 }
329 
std::ostream & operator<<(std::ostream &o, const allow_t a)
Definition: Acl.h:157
#define CBDATA_NAMESPACED_CLASS_INIT(namespace, type)
Definition: cbdata.h:326
#define assert(EX)
Definition: assert.h:17
void const char HLPCB * callback
Definition: stub_helper.cc:16
const char * wordlistAdd(wordlist **list, const char *key)
Definition: wordlist.cc:25
SBuf & assign(const SBuf &S)
Definition: SBuf.cc:83
std::string const & getBody() const
Current body. If parsing is not finished the method returns incompleted body.
Definition: cbdata.cc:60
static LruCache * HelperCache
cache for cert validation helper
Definition: helper.h:58
static const std::string code_cert_validate
String code for &quot;cert_validate&quot; messages.
Definition: SBuf.h:86
void composeRequest(CertValidationRequest const &vcert)
struct _request * request(char *urlin)
Definition: tcp-banger2.c:291
void add(const SBuf &key, const SBuf &value)
Definition: Notes.cc:280
void error(char *format,...)
#define xstrdup
SBuf & append(const SBuf &S)
Definition: SBuf.cc:195
Security::SessionPointer ssl
Definition: helper.cc:248
static void Init()
Init helper structure.
Definition: helper.cc:72
Definition: helper.h:60
AsyncCall::Pointer callback
Definition: helper.cc:247
#define safe_free(x)
Definition: xalloc.h:73
static void Shutdown()
Shutdown helper structure.
Definition: helper.cc:103
void wordlistDestroy(wordlist **list)
destroy a wordlist
Definition: wordlist.cc:16
void helperShutdown(helper *hlp)
Definition: helper.cc:616
std::unordered_map< SBuf, GeneratorRequest * > GeneratorRequests
Ssl::Helper query:GeneratorRequest map.
Definition: helper.cc:52
#define Must(condition)
Like assert() but throws an exception instead of aborting the process.
Definition: TextException.h:69
SBuf query
Definition: helper.cc:243
AnyP::PortCfgPointer HttpPortList
list of Squid http(s)_port configured
Definition: PortCfg.cc:21
GeneratorRequestor(HLPCB *aCallback, void *aData)
Definition: helper.cc:31
static void Submit(Ssl::CertValidationRequest const &request, AsyncCall::Pointer &)
Submit crtd request message to external crtd server.
Definition: helper.cc:290
char * strwordtok(char *buf, char **t)
Definition: String.cc:407
void HLPCB(void *, const Helper::Reply &)
Definition: forward.h:27
void const char HLPCB void * data
Definition: stub_helper.cc:16
NotePairs notes
Definition: Reply.h:61
virtual CallDialer * getDialer()=0
Security::SessionPointer ssl
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Debug.h:124
#define DBG_IMPORTANT
Definition: Debug.h:46
static void Reconfigure()
Definition: helper.cc:114
std::vector< GeneratorRequestor > GeneratorRequestors
Ssl::Helper request initiators waiting for the same answer (FIFO).
Definition: helper.cc:47
static void HandleGeneratorReply(void *data, const ::Helper::Reply &reply)
receives helper response
Definition: helper.cc:149
#define IPC_STREAM
Definition: defines.h:161
Definition: LruMap.h:17
#define CBDATA_CLASS(type)
Definition: cbdata.h:302
CallbackData data
Definition: helper.cc:33
Value value
instance identifier
Definition: InstanceId.h:42
static helper * ssl_crt_validator
helper for management of ssl_crtd.
Definition: helper.h:55
void Init(void)
prepares to parse ACLs configuration
Definition: AclRegs.cc:114
void emplace(HLPCB *callback, void *data)
adds a GeneratorRequestor
Definition: helper.cc:42
const char * c_str()
Definition: SBuf.cc:526
void helperOpenServers(helper *hlp)
Definition: helper.cc:125
void setCode(std::string const &aCode)
Set new request/reply code to compose.
static Ssl::GeneratorRequests TheGeneratorRequests
pending Ssl::Helper requests (to all certificate generator helpers combined)
Definition: helper.cc:68
static void Shutdown()
Shutdown helper structure.
Definition: helper.cc:218
std::string compose() const
LruMap< SBuf, Ssl::CertValidationResponse::Pointer, sizeof(Ssl::CertValidationResponse::Pointer)+sizeof(Ssl::CertValidationResponse)> LruCache
Definition: helper.h:57
GeneratorRequestors requestors
Definition: helper.cc:48
#define ScheduleCallHere(call)
Definition: AsyncCall.h:166
an old-style void* callback parameter
Definition: cbdata.h:376
static helper * ssl_crtd
helper for management of ssl_crtd.
Definition: helper.h:37
static void Reconfigure()
Definition: helper.cc:235
#define CBDATA_CLASS_INIT(type)
Definition: cbdata.h:318
ParseResult parse(const char *buffer, size_t len)
Definition: crtd_message.cc:21
void * data
Definition: cbdata.cc:123
RefCount< CertValidationResponse > Pointer
static void Init()
Init helper structure.
Definition: helper.cc:167
Initiator of an Ssl::Helper query.
Definition: helper.cc:29
SBuf query
Ssl::Helper request message (GeneratorRequests key)
Definition: helper.cc:44
#define xfree
static void Submit(CrtdMessage const &message, HLPCB *callback, void *data)
Submit crtd message to external crtd server.
Definition: helper.cc:120
Config TheConfig
Definition: Config.cc:12
const InstanceId< SBuf > id
Definition: SBuf.h:593
A pending Ssl::Helper request, combining the original and collapsed queries.
Definition: helper.cc:37
#define NULL
Definition: types.h:166
static void sslCrtvdHandleReplyWrapper(void *data, const ::Helper::Reply &reply)
Definition: helper.cc:253
bool parseResponse(CertValidationResponse &resp, std::string &error)
Parse a response message and fill the resp object with parsed informations.
std::shared_ptr< SSL > SessionPointer
Definition: Session.h:41

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors