]> git.ipfire.org Git - thirdparty/squid.git/blame - src/ssl/crtd_message.cc
SourceFormat Enforcement
[thirdparty/squid.git] / src / ssl / crtd_message.cc
CommitLineData
f7f3304a 1#include "squid.h"
95d2589c 2#include "ssl/crtd_message.h"
602d9612 3#include "ssl/gadgets.h"
95d2589c
CT
4#if HAVE_CSTDLIB
5#include <cstdlib>
6#endif
7#if HAVE_CSTRING
8#include <cstring>
9#endif
00fc192d
AR
10#if HAVE_STDEXCEPT
11#include <stdexcept>
12#endif
95d2589c 13
ff2d7d92
CT
14Ssl::CrtdMessage::CrtdMessage(MessageKind kind)
15 : body_size(0), state(kind == REPLY ? BEFORE_LENGTH: BEFORE_CODE)
95d2589c
CT
16{}
17
18Ssl::CrtdMessage::ParseResult Ssl::CrtdMessage::parse(const char * buffer, size_t len)
19{
20 char const *current_pos = buffer;
21 while (current_pos != buffer + len && state != END) {
22 switch (state) {
23 case BEFORE_CODE: {
24 if (xisspace(*current_pos)) {
d7ae3534 25 ++current_pos;
95d2589c
CT
26 break;
27 }
28 if (xisalpha(*current_pos)) {
29 state = CODE;
30 break;
31 }
32 clear();
33 return ERROR;
34 }
35 case CODE: {
36 if (xisalnum(*current_pos) || *current_pos == '_') {
37 current_block += *current_pos;
d7ae3534 38 ++current_pos;
95d2589c
CT
39 break;
40 }
41 if (xisspace(*current_pos)) {
42 code = current_block;
43 current_block.clear();
44 state = BEFORE_LENGTH;
45 break;
46 }
47 clear();
48 return ERROR;
49 }
50 case BEFORE_LENGTH: {
51 if (xisspace(*current_pos)) {
d7ae3534 52 ++current_pos;
95d2589c
CT
53 break;
54 }
55 if (xisdigit(*current_pos)) {
56 state = LENGTH;
57 break;
58 }
59 clear();
60 return ERROR;
61 }
62 case LENGTH: {
63 if (xisdigit(*current_pos)) {
64 current_block += *current_pos;
d7ae3534 65 ++current_pos;
95d2589c
CT
66 break;
67 }
68 if (xisspace(*current_pos)) {
69 body_size = atoi(current_block.c_str());
70 current_block.clear();
71 state = BEFORE_BODY;
72 break;
73 }
74 clear();
75 return ERROR;
76 }
77 case BEFORE_BODY: {
78 if (body_size == 0) {
79 state = END;
80 break;
81 }
82 if (xisspace(*current_pos)) {
d7ae3534 83 ++current_pos;
95d2589c
CT
84 break;
85 } else {
86 state = BODY;
87 break;
88 }
89 }
90 case BODY: {
91 size_t body_len = (static_cast<size_t>(buffer + len - current_pos) >= body_size - current_block.length())
92 ? body_size - current_block.length()
93 : static_cast<size_t>(buffer + len - current_pos);
94 current_block += std::string(current_pos, body_len);
95 current_pos += body_len;
96 if (current_block.length() == body_size) {
97 body = current_block;
98 state = END;
99 }
100 if (current_block.length() > body_size) {
101 clear();
102 return ERROR;
103 }
104 break;
105 }
106 case END: {
107 return OK;
108 }
109 }
110 }
111 if (state != END) return INCOMPLETE;
112 return OK;
113}
114
115std::string const & Ssl::CrtdMessage::getBody() const { return body; }
116
117std::string const & Ssl::CrtdMessage::getCode() const { return code; }
118
119void Ssl::CrtdMessage::setBody(std::string const & aBody) { body = aBody; }
120
121void Ssl::CrtdMessage::setCode(std::string const & aCode) { code = aCode; }
122
95d2589c
CT
123std::string Ssl::CrtdMessage::compose() const
124{
125 if (code.empty()) return std::string();
126 char buffer[10];
127 snprintf(buffer, sizeof(buffer), "%zd", body.length());
0af9303a 128 return code + ' ' + buffer + ' ' + body;
95d2589c
CT
129}
130
131void Ssl::CrtdMessage::clear()
132{
133 body_size = 0;
134 state = BEFORE_CODE;
135 body.clear();
136 code.clear();
137 current_block.clear();
138}
139
140void Ssl::CrtdMessage::parseBody(CrtdMessage::BodyParams & map, std::string & other_part) const
141{
142 other_part.clear();
143 // Copy string for using it as temp buffer.
144 std::string temp_body(body.c_str(), body.length());
145 char * buffer = const_cast<char *>(temp_body.c_str());
146 char * token = strtok(buffer, "\r\n");
147 while (token != NULL) {
148 std::string current_string(token);
149 size_t equal_pos = current_string.find('=');
150 if (equal_pos == std::string::npos) {
151 size_t offset_body_part = token - temp_body.c_str();
152 other_part = std::string(body.c_str() + offset_body_part, body.length() - offset_body_part);
153 break;
154 } else {
155 std::string param(current_string.c_str(), current_string.c_str() + equal_pos);
156 std::string value(current_string.c_str() + equal_pos + 1);
157 map.insert(std::make_pair(param, value));
158 }
159 token = strtok(NULL, "\r\n");
160 }
161}
162
163void Ssl::CrtdMessage::composeBody(CrtdMessage::BodyParams const & map, std::string const & other_part)
164{
165 body.clear();
d7ae3534 166 for (BodyParams::const_iterator i = map.begin(); i != map.end(); ++i) {
95d2589c
CT
167 if (i != map.begin())
168 body += "\n";
169 body += i->first + "=" + i->second;
170 }
171 if (!other_part.empty())
4e903d59 172 body += '\n' + other_part;
95d2589c
CT
173}
174
ce394ae1 175bool Ssl::CrtdMessage::parseRequest(Ssl::CertificateProperties &certProperties, std::string &error)
06997a38
CT
176{
177 Ssl::CrtdMessage::BodyParams map;
178 std::string certs_part;
179 parseBody(map, certs_part);
180 Ssl::CrtdMessage::BodyParams::iterator i = map.find(Ssl::CrtdMessage::param_host);
181 if (i == map.end()) {
ce394ae1 182 error = "Cannot find \"host\" parameter in request message";
06997a38
CT
183 return false;
184 }
185 certProperties.commonName = i->second;
87f237a9
A
186
187 i = map.find(Ssl::CrtdMessage::param_SetValidAfter);
06997a38
CT
188 if (i != map.end() && strcasecmp(i->second.c_str(), "on") == 0)
189 certProperties.setValidAfter = true;
87f237a9 190
06997a38
CT
191 i = map.find(Ssl::CrtdMessage::param_SetValidBefore);
192 if (i != map.end() && strcasecmp(i->second.c_str(), "on") == 0)
193 certProperties.setValidBefore = true;
194
195 i = map.find(Ssl::CrtdMessage::param_SetCommonName);
196 if (i != map.end()) {
87f237a9 197 // use this as Common Name instead of the hostname
06997a38
CT
198 // defined with host or Common Name from mimic cert
199 certProperties.commonName = i->second;
200 certProperties.setCommonName = true;
201 }
202
203 i = map.find(Ssl::CrtdMessage::param_Sign);
204 if (i != map.end()) {
205 if ((certProperties.signAlgorithm = Ssl::certSignAlgorithmId(i->second.c_str())) == Ssl::algSignEnd) {
ce394ae1 206 error = "Wrong signing algoritm: " + i->second;
06997a38
CT
207 return false;
208 }
87f237a9 209 } else
06997a38
CT
210 certProperties.signAlgorithm = Ssl::algSignTrusted;
211
5cc307f3 212 if (!Ssl::readCertAndPrivateKeyFromMemory(certProperties.signWithX509, certProperties.signWithPkey, certs_part.c_str())) {
ce394ae1 213 error = "Broken signing certificate!";
06997a38
CT
214 return false;
215 }
216
217 static const std::string CERT_BEGIN_STR("-----BEGIN CERTIFICATE");
218 size_t pos;
219 if ((pos = certs_part.find(CERT_BEGIN_STR)) != std::string::npos) {
220 pos += CERT_BEGIN_STR.length();
221 if ((pos= certs_part.find(CERT_BEGIN_STR, pos)) != std::string::npos)
222 Ssl::readCertFromMemory(certProperties.mimicCert, certs_part.c_str() + pos);
223 }
224 return true;
225}
226
227void Ssl::CrtdMessage::composeRequest(Ssl::CertificateProperties const &certProperties)
228{
229 body.clear();
230 body = Ssl::CrtdMessage::param_host + "=" + certProperties.commonName;
231 if (certProperties.setCommonName)
232 body += "\n" + Ssl::CrtdMessage::param_SetCommonName + "=" + certProperties.commonName;
233 if (certProperties.setValidAfter)
234 body += "\n" + Ssl::CrtdMessage::param_SetValidAfter + "=on";
235 if (certProperties.setValidBefore)
236 body += "\n" + Ssl::CrtdMessage::param_SetValidBefore + "=on";
87f237a9 237 if (certProperties.signAlgorithm != Ssl::algSignEnd)
06997a38
CT
238 body += "\n" + Ssl::CrtdMessage::param_Sign + "=" + certSignAlgorithm(certProperties.signAlgorithm);
239
240 std::string certsPart;
1b78835c 241 if (!Ssl::writeCertAndPrivateKeyToMemory(certProperties.signWithX509, certProperties.signWithPkey, certsPart))
00fc192d 242 throw std::runtime_error("Ssl::writeCertAndPrivateKeyToMemory()");
06997a38 243 if (certProperties.mimicCert.get()) {
00fc192d
AR
244 if (!Ssl::appendCertToMemory(certProperties.mimicCert, certsPart))
245 throw std::runtime_error("Ssl::appendCertToMemory()");
06997a38
CT
246 }
247 body += "\n" + certsPart;
248}
249
95d2589c
CT
250const std::string Ssl::CrtdMessage::code_new_certificate("new_certificate");
251const std::string Ssl::CrtdMessage::param_host("host");
fb2178bb
CT
252const std::string Ssl::CrtdMessage::param_SetValidAfter(Ssl::CertAdaptAlgorithmStr[algSetValidAfter]);
253const std::string Ssl::CrtdMessage::param_SetValidBefore(Ssl::CertAdaptAlgorithmStr[algSetValidBefore]);
254const std::string Ssl::CrtdMessage::param_SetCommonName(Ssl::CertAdaptAlgorithmStr[algSetCommonName]);
aebe6888 255const std::string Ssl::CrtdMessage::param_Sign("Sign");