crtd_message.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2019 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 "ssl/crtd_message.h"
11 #include "ssl/gadgets.h"
12 
13 #include <cstdlib>
14 #include <cstring>
15 #include <stdexcept>
16 
18  : body_size(0), state(kind == REPLY ? BEFORE_LENGTH: BEFORE_CODE)
19 {}
20 
22 {
23  char const *current_pos = buffer;
24  while (current_pos != buffer + len && state != END) {
25  switch (state) {
26  case BEFORE_CODE: {
27  if (xisspace(*current_pos)) {
28  ++current_pos;
29  break;
30  }
31  if (xisalpha(*current_pos)) {
32  state = CODE;
33  break;
34  }
35  clear();
36  return ERROR;
37  }
38  case CODE: {
39  if (xisalnum(*current_pos) || *current_pos == '_') {
40  current_block += *current_pos;
41  ++current_pos;
42  break;
43  }
44  if (xisspace(*current_pos)) {
46  current_block.clear();
48  break;
49  }
50  clear();
51  return ERROR;
52  }
53  case BEFORE_LENGTH: {
54  if (xisspace(*current_pos)) {
55  ++current_pos;
56  break;
57  }
58  if (xisdigit(*current_pos)) {
59  state = LENGTH;
60  break;
61  }
62  clear();
63  return ERROR;
64  }
65  case LENGTH: {
66  if (xisdigit(*current_pos)) {
67  current_block += *current_pos;
68  ++current_pos;
69  break;
70  }
71  if (xisspace(*current_pos)) {
72  body_size = atoi(current_block.c_str());
73  current_block.clear();
75  break;
76  }
77  clear();
78  return ERROR;
79  }
80  case BEFORE_BODY: {
81  if (body_size == 0) {
82  state = END;
83  break;
84  }
85  if (xisspace(*current_pos)) {
86  ++current_pos;
87  break;
88  } else {
89  state = BODY;
90  break;
91  }
92  }
93  case BODY: {
94  size_t body_len = (static_cast<size_t>(buffer + len - current_pos) >= body_size - current_block.length())
95  ? body_size - current_block.length()
96  : static_cast<size_t>(buffer + len - current_pos);
97  current_block += std::string(current_pos, body_len);
98  current_pos += body_len;
99  if (current_block.length() == body_size) {
101  state = END;
102  }
103  if (current_block.length() > body_size) {
104  clear();
105  return ERROR;
106  }
107  break;
108  }
109  case END: {
110  return OK;
111  }
112  }
113  }
114  if (state != END) return INCOMPLETE;
115  return OK;
116 }
117 
118 std::string const & Ssl::CrtdMessage::getBody() const { return body; }
119 
120 std::string const & Ssl::CrtdMessage::getCode() const { return code; }
121 
122 void Ssl::CrtdMessage::setBody(std::string const & aBody) { body = aBody; }
123 
124 void Ssl::CrtdMessage::setCode(std::string const & aCode) { code = aCode; }
125 
126 std::string Ssl::CrtdMessage::compose() const
127 {
128  if (code.empty()) return std::string();
129  char buffer[10];
130  snprintf(buffer, sizeof(buffer), "%zd", body.length());
131  return code + ' ' + buffer + ' ' + body;
132 }
133 
135 {
136  body_size = 0;
137  state = BEFORE_CODE;
138  body.clear();
139  code.clear();
140  current_block.clear();
141 }
142 
143 void Ssl::CrtdMessage::parseBody(CrtdMessage::BodyParams & map, std::string & other_part) const
144 {
145  other_part.clear();
146  // Copy string for using it as temp buffer.
147  std::string temp_body(body.c_str(), body.length());
148  char * buffer = const_cast<char *>(temp_body.c_str());
149  char * token = strtok(buffer, "\r\n");
150  while (token != NULL) {
151  std::string current_string(token);
152  size_t equal_pos = current_string.find('=');
153  if (equal_pos == std::string::npos) {
154  size_t offset_body_part = token - temp_body.c_str();
155  other_part = std::string(body.c_str() + offset_body_part, body.length() - offset_body_part);
156  break;
157  } else {
158  std::string param(current_string.c_str(), current_string.c_str() + equal_pos);
159  std::string value(current_string.c_str() + equal_pos + 1);
160  map.insert(std::make_pair(param, value));
161  }
162  token = strtok(NULL, "\r\n");
163  }
164 }
165 
166 void Ssl::CrtdMessage::composeBody(CrtdMessage::BodyParams const & map, std::string const & other_part)
167 {
168  body.clear();
169  for (BodyParams::const_iterator i = map.begin(); i != map.end(); ++i) {
170  if (i != map.begin())
171  body += "\n";
172  body += i->first + "=" + i->second;
173  }
174  if (!other_part.empty())
175  body += '\n' + other_part;
176 }
177 
179 {
181  std::string certs_part;
182  parseBody(map, certs_part);
183  Ssl::CrtdMessage::BodyParams::iterator i = map.find(Ssl::CrtdMessage::param_host);
184  if (i == map.end()) {
185  error = "Cannot find \"host\" parameter in request message";
186  return false;
187  }
188  certProperties.commonName = i->second;
189 
191  if (i != map.end() && strcasecmp(i->second.c_str(), "on") == 0)
192  certProperties.setValidAfter = true;
193 
195  if (i != map.end() && strcasecmp(i->second.c_str(), "on") == 0)
196  certProperties.setValidBefore = true;
197 
199  if (i != map.end()) {
200  // use this as Common Name instead of the hostname
201  // defined with host or Common Name from mimic cert
202  certProperties.commonName = i->second;
203  certProperties.setCommonName = true;
204  }
205 
206  i = map.find(Ssl::CrtdMessage::param_Sign);
207  if (i != map.end()) {
208  if ((certProperties.signAlgorithm = Ssl::certSignAlgorithmId(i->second.c_str())) == Ssl::algSignEnd) {
209  error = "Wrong signing algoritm: ";
210  error += i->second;
211  return false;
212  }
213  } else
214  certProperties.signAlgorithm = Ssl::algSignTrusted;
215 
216  i = map.find(Ssl::CrtdMessage::param_SignHash);
217  const char *signHashName = i != map.end() ? i->second.c_str() : SQUID_SSL_SIGN_HASH_IF_NONE;
218  if (!(certProperties.signHash = EVP_get_digestbyname(signHashName))) {
219  error = "Wrong signing hash: ";
220  error += signHashName;
221  return false;
222  }
223 
224  if (!Ssl::readCertAndPrivateKeyFromMemory(certProperties.signWithX509, certProperties.signWithPkey, certs_part.c_str())) {
225  error = "Broken signing certificate!";
226  return false;
227  }
228 
229  static const std::string CERT_BEGIN_STR("-----BEGIN CERTIFICATE");
230  size_t pos;
231  if ((pos = certs_part.find(CERT_BEGIN_STR)) != std::string::npos) {
232  pos += CERT_BEGIN_STR.length();
233  if ((pos= certs_part.find(CERT_BEGIN_STR, pos)) != std::string::npos)
234  Ssl::readCertFromMemory(certProperties.mimicCert, certs_part.c_str() + pos);
235  }
236  return true;
237 }
238 
240 {
241  body.clear();
242  body = Ssl::CrtdMessage::param_host + "=" + certProperties.commonName;
243  if (certProperties.setCommonName)
244  body += "\n" + Ssl::CrtdMessage::param_SetCommonName + "=" + certProperties.commonName;
245  if (certProperties.setValidAfter)
247  if (certProperties.setValidBefore)
249  if (certProperties.signAlgorithm != Ssl::algSignEnd)
250  body += "\n" + Ssl::CrtdMessage::param_Sign + "=" + certSignAlgorithm(certProperties.signAlgorithm);
251  if (certProperties.signHash)
252  body += "\n" + Ssl::CrtdMessage::param_SignHash + "=" + EVP_MD_name(certProperties.signHash);
253 
254  std::string certsPart;
255  if (!Ssl::writeCertAndPrivateKeyToMemory(certProperties.signWithX509, certProperties.signWithPkey, certsPart))
256  throw std::runtime_error("Ssl::writeCertAndPrivateKeyToMemory()");
257  if (certProperties.mimicCert.get()) {
258  if (!Ssl::appendCertToMemory(certProperties.mimicCert, certsPart))
259  throw std::runtime_error("Ssl::appendCertToMemory()");
260  }
261  body += "\n" + certsPart;
262 }
263 
264 const std::string Ssl::CrtdMessage::code_new_certificate("new_certificate");
265 const std::string Ssl::CrtdMessage::param_host("host");
269 const std::string Ssl::CrtdMessage::param_Sign("Sign");
270 const std::string Ssl::CrtdMessage::param_SignHash("SignHash");
271 
bool setCommonName
Replace the CN field of the mimicing subject with the given.
Definition: gadgets.h:221
static const std::string param_SetCommonName
Parameter name for passing SetCommonName cert adaptation variable.
Definition: crtd_message.h:84
void setBody(std::string const &aBody)
Set new body to encode.
CrtdMessage(MessageKind kind)
Definition: crtd_message.cc:17
bool setValidAfter
Do not mimic "Not Valid After" field.
Definition: gadgets.h:219
static const std::string param_SetValidAfter
Parameter name for passing SetValidAfter cert adaptation variable.
Definition: crtd_message.h:80
bool setValidBefore
Do not mimic "Not Valid Before" field.
Definition: gadgets.h:220
void parseBody(BodyParams &map, std::string &other_part) const
void error(char *format,...)
int i
Definition: membanger.c:49
T * get() const
Returns raw and possibly nullptr pointer.
std::string current_block
Current block buffer.
Definition: crtd_message.h:103
void composeBody(BodyParams const &map, std::string const &other_part)
std::string const & getCode() const
Current response/request code. If parsing is not finished the method may return incompleted code...
std::string commonName
A CN to use for the generated certificate.
Definition: gadgets.h:222
const char * CertAdaptAlgorithmStr[]
Definition: gadgets.cc:202
#define xisspace(x)
Definition: xis.h:17
std::string const & getBody() const
Current body. If parsing is not finished the method returns incompleted body.
std::map< std::string, std::string > BodyParams
Definition: crtd_message.h:27
static const std::string param_SetValidBefore
Parameter name for passing SetValidBefore cert adaptation variable.
Definition: crtd_message.h:82
static const std::string code_new_certificate
String code for "new_certificate" messages.
Definition: crtd_message.h:76
Security::PrivateKeyPointer signWithPkey
The key of the signing certificate.
Definition: gadgets.h:218
std::string code
Current response/request code.
Definition: crtd_message.h:102
Security::CertPointer mimicCert
Certificate to mimic.
Definition: gadgets.h:216
const char * certSignAlgorithm(int sg)
Definition: gadgets.h:163
std::string body
Current body.
Definition: crtd_message.h:101
ParseState state
Parsing state.
Definition: crtd_message.h:100
bool appendCertToMemory(Security::CertPointer const &cert, std::string &bufferToWrite)
Definition: gadgets.cc:92
CertSignAlgorithm certSignAlgorithmId(const char *sg)
Definition: gadgets.h:175
std::string compose() const
static const std::string param_SignHash
The signing hash to use.
Definition: crtd_message.h:88
ParseResult
Parse result codes.
Definition: crtd_message.h:29
void setCode(std::string const &aCode)
Set new request/reply code to compose.
int unsigned int const char *desc STUB void int len
Definition: stub_fd.cc:20
CertSignAlgorithm signAlgorithm
The signing algorithm to use.
Definition: gadgets.h:223
Security::CertPointer signWithX509
Certificate to sign the generated request.
Definition: gadgets.h:217
void composeRequest(Ssl::CertificateProperties const &)
bool readCertFromMemory(Security::CertPointer &cert, char const *bufferToRead)
Definition: gadgets.cc:134
#define SQUID_SSL_SIGN_HASH_IF_NONE
Definition: gadgets.h:39
#define xisdigit(x)
Definition: xis.h:20
static const std::string param_Sign
Parameter name for passing signing algorithm.
Definition: crtd_message.h:86
bool parseRequest(Ssl::CertificateProperties &, std::string &error)
orchestrates entire request parsing
bool writeCertAndPrivateKeyToMemory(Security::CertPointer const &cert, Security::PrivateKeyPointer const &pkey, std::string &bufferToWrite)
Definition: gadgets.cc:68
#define xisalnum(x)
Definition: xis.h:25
ParseResult parse(const char *buffer, size_t len)
Definition: crtd_message.cc:21
bool readCertAndPrivateKeyFromMemory(Security::CertPointer &cert, Security::PrivateKeyPointer &pkey, char const *bufferToRead)
Definition: gadgets.cc:116
const EVP_MD * signHash
The signing hash to use.
Definition: gadgets.h:224
#define xisalpha(x)
Definition: xis.h:23
#define NULL
Definition: types.h:166
size_t body_size
The body size if exist or 0.
Definition: crtd_message.h:99
static const std::string param_host
Parameter name for passing hostname.
Definition: crtd_message.h:78
void clear()
Reset the class.

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors