]> git.ipfire.org Git - thirdparty/squid.git/blame - src/ssl/cert_validate_message.cc
Redo r12887 (bug 2066 fix) which introduced several related bugs:
[thirdparty/squid.git] / src / ssl / cert_validate_message.cc
CommitLineData
a1f04d64 1#include "squid.h"
77dce8a5 2#include "acl/FilledChecklist.h"
a9b6afe1 3#include "helper.h"
a1f04d64
AR
4#include "ssl/support.h"
5#include "ssl/cert_validate_message.h"
6#include "ssl/ErrorDetail.h"
7
3a7d782f 8void
b56756cb 9Ssl::CertValidationMsg::composeRequest(CertValidationRequest const &vcert)
a1f04d64
AR
10{
11 body.clear();
b56756cb 12 body += Ssl::CertValidationMsg::param_host + "=" + vcert.domainName;
a1f04d64 13 if (vcert.errors) {
b56756cb 14 body += "\n" + Ssl::CertValidationMsg::param_error + "=";
a1f04d64
AR
15 bool comma = false;
16 for (const Ssl::Errors *err = vcert.errors; err; err = err->next ) {
17 if (comma)
18 body += ",";
19 body += GetErrorName(err->element);
20 comma = true;
21 }
22 }
23
14798e73
CT
24 STACK_OF(X509) *peerCerts = SSL_get_peer_cert_chain(vcert.ssl);
25 if (peerCerts) {
a1f04d64
AR
26 body +="\n";
27 Ssl::BIO_Pointer bio(BIO_new(BIO_s_mem()));
14798e73
CT
28 for (int i = 0; i < sk_X509_num(peerCerts); ++i) {
29 X509 *cert = sk_X509_value(peerCerts, i);
a1f04d64
AR
30 PEM_write_bio_X509(bio.get(), cert);
31 body = body + "cert_" + xitoa(i) + "=";
32 char *ptr;
33 long len = BIO_get_mem_data(bio.get(), &ptr);
34 body.append(ptr, len);
35 // Normally openssl toolkit terminates Certificate with a '\n'.
36 if (ptr[len-1] != '\n')
37 body +="\n";
38 if (!BIO_reset(bio.get())) {
39 // print an error?
40 }
41 }
42 }
43}
44
3a7d782f
CT
45static int
46get_error_id(const char *label, size_t len)
a1f04d64
AR
47{
48 const char *e = label + len -1;
49 while (e != label && xisdigit(*e)) --e;
50 if (e != label) ++e;
51 return strtol(e, 0 , 10);
52}
53
3a7d782f 54bool
b56756cb 55Ssl::CertValidationMsg::parseResponse(CertValidationResponse &resp, STACK_OF(X509) *peerCerts, std::string &error)
a1f04d64 56{
3a7d782f 57 std::vector<CertItem> certs;
a1f04d64
AR
58
59 const char *param = body.c_str();
22636a68
CT
60 while (*param) {
61 while (xisspace(*param)) param++;
a1f04d64
AR
62 if (! *param)
63 break;
64
65 size_t param_len = strcspn(param, "=\r\n");
66 if (param[param_len] != '=') {
4a77bb4e 67 debugs(83, DBG_IMPORTANT, "WARNING: cert validator response parse error: " << param);
a1f04d64
AR
68 return false;
69 }
70 const char *value=param+param_len+1;
71
22636a68
CT
72 if (param_len > param_cert.length() &&
73 strncmp(param, param_cert.c_str(), param_cert.length()) == 0) {
3a7d782f 74 CertItem ci;
22636a68 75 ci.name.assign(param, param_len);
a1f04d64
AR
76 X509_Pointer x509;
77 readCertFromMemory(x509, value);
78 ci.setCert(x509.get());
79 certs.push_back(ci);
80
81 const char *b = strstr(value, "-----END CERTIFICATE-----");
82 if (b == NULL) {
4a77bb4e 83 debugs(83, DBG_IMPORTANT, "WARNING: cert Validator response parse error: Failed to find certificate boundary " << value);
a1f04d64
AR
84 return false;
85 }
86 b += strlen("-----END CERTIFICATE-----");
87 param = b + 1;
88 continue;
89 }
90
91 size_t value_len = strcspn(value, "\r\n");
92 std::string v(value, value_len);
93
4a77bb4e 94 debugs(83, 5, "Returned value: " << std::string(param, param_len).c_str() << ": " <<
a1f04d64
AR
95 v.c_str());
96
97 int errorId = get_error_id(param, param_len);
b56756cb 98 Ssl::CertValidationResponse::RecvdError &currentItem = resp.getError(errorId);
a1f04d64 99
22636a68
CT
100 if (param_len > param_error_name.length() &&
101 strncmp(param, param_error_name.c_str(), param_error_name.length()) == 0) {
a1f04d64 102 currentItem.error_no = Ssl::GetErrorCode(v.c_str());
3a7d782f 103 if (currentItem.error_no == SSL_ERROR_NONE) {
4a77bb4e 104 debugs(83, DBG_IMPORTANT, "WARNING: cert validator response parse error: Unknown SSL Error: " << v);
3a7d782f
CT
105 return false;
106 }
22636a68 107 } else if (param_len > param_error_reason.length() &&
a1f04d64
AR
108 strncmp(param, param_error_reason.c_str(), param_error_reason.length()) == 0) {
109 currentItem.error_reason = v;
110 } else if (param_len > param_error_cert.length() &&
111 strncmp(param, param_error_cert.c_str(), param_error_cert.length()) == 0) {
112
3a7d782f 113 if (X509 *cert = getCertByName(certs, v)) {
4a77bb4e 114 debugs(83, 6, "The certificate with id \"" << v << "\" found.");
3a7d782f
CT
115 currentItem.setCert(cert);
116 } else {
117 //In this case we assume that the certID is one of the certificates sent
118 // to cert validator. The certificates sent to cert validator have names in
119 // form "cert_xx" where the "xx" is an integer represents the position of
120 // the certificate inside peer certificates list.
b56756cb 121 const int certId = get_error_id(v.c_str(), v.length());
4a77bb4e 122 debugs(83, 6, "Cert index in peer certificates list:" << certId);
77dce8a5
CT
123 //if certId is not correct sk_X509_value returns NULL
124 currentItem.setCert(sk_X509_value(peerCerts, certId));
a1f04d64 125 }
3a7d782f 126 } else {
4a77bb4e 127 debugs(83, DBG_IMPORTANT, "WARNING: cert validator response parse error: Unknown parameter name " << std::string(param, param_len).c_str());
3a7d782f
CT
128 return false;
129 }
a1f04d64
AR
130
131 param = value + value_len +1;
132 }
133
3a7d782f 134 /*Run through parsed errors to check for errors*/
bc624572
CT
135 typedef Ssl::CertValidationResponse::RecvdErrors::const_iterator SVCRECI;
136 for (SVCRECI i = resp.errors.begin(); i != resp.errors.end(); ++i) {
46901eed 137 if (i->error_no == SSL_ERROR_NONE) {
bc624572
CT
138 debugs(83, DBG_IMPORTANT, "WARNING: cert validator incomplete response: Missing error name from error_id: " << i->id);
139 return false;
140 }
141 }
a1f04d64
AR
142
143 return true;
144}
145
3a7d782f 146X509 *
b56756cb 147Ssl::CertValidationMsg::getCertByName(std::vector<CertItem> const &certs, std::string const & name)
3a7d782f 148{
6136ab56
CT
149 typedef std::vector<CertItem>::const_iterator SVCI;
150 for (SVCI ci = certs.begin(); ci != certs.end(); ++ci) {
3a7d782f 151 if (ci->name.compare(name) == 0)
4a77bb4e 152 return ci->cert.get();
3a7d782f
CT
153 }
154 return NULL;
155}
156
b56756cb
CT
157Ssl::CertValidationResponse::RecvdError &
158Ssl::CertValidationResponse::getError(int errorId)
3a7d782f 159{
6136ab56 160 typedef Ssl::CertValidationResponse::RecvdErrors::iterator SVCREI;
22636a68 161 for (SVCREI i = errors.begin(); i != errors.end(); ++i) {
3a7d782f
CT
162 if (i->id == errorId)
163 return *i;
164 }
b56756cb 165 Ssl::CertValidationResponse::RecvdError errItem;
3a7d782f
CT
166 errItem.id = errorId;
167 errors.push_back(errItem);
168 return errors.back();
169}
170
22636a68
CT
171Ssl::CertValidationResponse::RecvdError::RecvdError(const RecvdError &old)
172{
bc624572 173 id = old.id;
a1f04d64
AR
174 error_no = old.error_no;
175 error_reason = old.error_reason;
4a77bb4e 176 setCert(old.cert.get());
a1f04d64
AR
177}
178
22636a68
CT
179Ssl::CertValidationResponse::RecvdError & Ssl::CertValidationResponse::RecvdError::operator = (const RecvdError &old)
180{
bc624572 181 id = old.id;
a1f04d64
AR
182 error_no = old.error_no;
183 error_reason = old.error_reason;
4a77bb4e 184 setCert(old.cert.get());
a1f04d64
AR
185 return *this;
186}
187
188void
22636a68
CT
189Ssl::CertValidationResponse::RecvdError::setCert(X509 *aCert)
190{
4a77bb4e 191 cert.resetAndLock(aCert);
a1f04d64
AR
192}
193
b56756cb 194Ssl::CertValidationMsg::CertItem::CertItem(const CertItem &old)
a1f04d64
AR
195{
196 name = old.name;
4a77bb4e 197 setCert(old.cert.get());
a1f04d64
AR
198}
199
b56756cb 200Ssl::CertValidationMsg::CertItem & Ssl::CertValidationMsg::CertItem::operator = (const CertItem &old)
a1f04d64
AR
201{
202 name = old.name;
4a77bb4e 203 setCert(old.cert.get());
a1f04d64
AR
204 return *this;
205}
206
a1f04d64 207void
b56756cb 208Ssl::CertValidationMsg::CertItem::setCert(X509 *aCert)
a1f04d64 209{
4a77bb4e 210 cert.resetAndLock(aCert);
a1f04d64
AR
211}
212
b56756cb
CT
213const std::string Ssl::CertValidationMsg::code_cert_validate("cert_validate");
214const std::string Ssl::CertValidationMsg::param_domain("domain");
215const std::string Ssl::CertValidationMsg::param_error("errors");
216const std::string Ssl::CertValidationMsg::param_cert("cert_");
22636a68 217const std::string Ssl::CertValidationMsg::param_error_name("error_name_");
b56756cb
CT
218const std::string Ssl::CertValidationMsg::param_error_reason("error_reason_");
219const std::string Ssl::CertValidationMsg::param_error_cert("error_cert_");
a1f04d64 220