]>
Commit | Line | Data |
---|---|---|
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 |
14 | Ssl::CrtdMessage::CrtdMessage(MessageKind kind) |
15 | : body_size(0), state(kind == REPLY ? BEFORE_LENGTH: BEFORE_CODE) | |
95d2589c CT |
16 | {} |
17 | ||
18 | Ssl::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 | ||
115 | std::string const & Ssl::CrtdMessage::getBody() const { return body; } | |
116 | ||
117 | std::string const & Ssl::CrtdMessage::getCode() const { return code; } | |
118 | ||
119 | void Ssl::CrtdMessage::setBody(std::string const & aBody) { body = aBody; } | |
120 | ||
121 | void Ssl::CrtdMessage::setCode(std::string const & aCode) { code = aCode; } | |
122 | ||
95d2589c CT |
123 | std::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 | ||
131 | void Ssl::CrtdMessage::clear() | |
132 | { | |
133 | body_size = 0; | |
134 | state = BEFORE_CODE; | |
135 | body.clear(); | |
136 | code.clear(); | |
137 | current_block.clear(); | |
138 | } | |
139 | ||
140 | void 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 | ||
163 | void 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 | 175 | bool 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 | ||
227 | void 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 |
250 | const std::string Ssl::CrtdMessage::code_new_certificate("new_certificate"); |
251 | const std::string Ssl::CrtdMessage::param_host("host"); | |
fb2178bb CT |
252 | const std::string Ssl::CrtdMessage::param_SetValidAfter(Ssl::CertAdaptAlgorithmStr[algSetValidAfter]); |
253 | const std::string Ssl::CrtdMessage::param_SetValidBefore(Ssl::CertAdaptAlgorithmStr[algSetValidBefore]); | |
254 | const std::string Ssl::CrtdMessage::param_SetCommonName(Ssl::CertAdaptAlgorithmStr[algSetCommonName]); | |
aebe6888 | 255 | const std::string Ssl::CrtdMessage::param_Sign("Sign"); |