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