2 #include "acl/FilledChecklist.h"
5 #include "ssl/cert_validate_message.h"
6 #include "ssl/ErrorDetail.h"
7 #include "ssl/support.h"
10 Ssl::CertValidationMsg::composeRequest(CertValidationRequest
const &vcert
)
13 body
+= Ssl::CertValidationMsg::param_host
+ "=" + vcert
.domainName
;
14 STACK_OF(X509
) *peerCerts
= static_cast<STACK_OF(X509
) *>(SSL_get_ex_data(vcert
.ssl
, ssl_ex_index_ssl_cert_chain
));
17 peerCerts
= SSL_get_peer_cert_chain(vcert
.ssl
);
20 Ssl::BIO_Pointer
bio(BIO_new(BIO_s_mem()));
21 for (int i
= 0; i
< sk_X509_num(peerCerts
); ++i
) {
22 X509
*cert
= sk_X509_value(peerCerts
, i
);
23 PEM_write_bio_X509(bio
.get(), cert
);
24 body
= body
+ "\n" + param_cert
+ xitoa(i
) + "=";
26 long len
= BIO_get_mem_data(bio
.get(), &ptr
);
27 body
.append(ptr
, (ptr
[len
-1] == '\n' ? len
- 1 : len
));
28 if (!BIO_reset(bio
.get())) {
36 for (const Ssl::CertErrors
*err
= vcert
.errors
; err
; err
= err
->next
, ++i
) {
38 body
= body
+ param_error_name
+ xitoa(i
) + "=" + GetErrorName(err
->element
.code
) + "\n";
39 int errorCertPos
= -1;
40 if (err
->element
.cert
.get())
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");
46 body
+= param_error_cert
+ xitoa(i
) + "=";
47 body
+= param_cert
+ xitoa((errorCertPos
>= 0 ? errorCertPos
: 0));
53 get_error_id(const char *label
, size_t len
)
55 const char *e
= label
+ len
-1;
56 while (e
!= label
&& xisdigit(*e
)) --e
;
58 return strtol(e
, 0 , 10);
62 Ssl::CertValidationMsg::parseResponse(CertValidationResponse
&resp
, STACK_OF(X509
) *peerCerts
, std::string
&error
)
64 std::vector
<CertItem
> certs
;
66 const char *param
= body
.c_str();
68 while (xisspace(*param
)) param
++;
72 size_t param_len
= strcspn(param
, "=\r\n");
73 if (param
[param_len
] != '=') {
74 debugs(83, DBG_IMPORTANT
, "WARNING: cert validator response parse error: " << param
);
77 const char *value
=param
+param_len
+1;
79 if (param_len
> param_cert
.length() &&
80 strncmp(param
, param_cert
.c_str(), param_cert
.length()) == 0) {
82 ci
.name
.assign(param
, param_len
);
84 readCertFromMemory(x509
, value
);
85 ci
.setCert(x509
.get());
88 const char *b
= strstr(value
, "-----END CERTIFICATE-----");
90 debugs(83, DBG_IMPORTANT
, "WARNING: cert Validator response parse error: Failed to find certificate boundary " << value
);
93 b
+= strlen("-----END CERTIFICATE-----");
98 size_t value_len
= strcspn(value
, "\r\n");
99 std::string
v(value
, value_len
);
101 debugs(83, 5, "Returned value: " << std::string(param
, param_len
).c_str() << ": " <<
104 int errorId
= get_error_id(param
, param_len
);
105 Ssl::CertValidationResponse::RecvdError
¤tItem
= resp
.getError(errorId
);
107 if (param_len
> param_error_name
.length() &&
108 strncmp(param
, param_error_name
.c_str(), param_error_name
.length()) == 0) {
109 currentItem
.error_no
= Ssl::GetErrorCode(v
.c_str());
110 if (currentItem
.error_no
== SSL_ERROR_NONE
) {
111 debugs(83, DBG_IMPORTANT
, "WARNING: cert validator response parse error: Unknown SSL Error: " << v
);
114 } else if (param_len
> param_error_reason
.length() &&
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) {
120 if (X509
*cert
= getCertByName(certs
, v
)) {
121 debugs(83, 6, "The certificate with id \"" << v
<< "\" found.");
122 currentItem
.setCert(cert
);
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.
128 const int certId
= get_error_id(v
.c_str(), v
.length());
129 debugs(83, 6, "Cert index in peer certificates list:" << certId
);
130 //if certId is not correct sk_X509_value returns NULL
131 currentItem
.setCert(sk_X509_value(peerCerts
, certId
));
134 debugs(83, DBG_IMPORTANT
, "WARNING: cert validator response parse error: Unknown parameter name " << std::string(param
, param_len
).c_str());
138 param
= value
+ value_len
+1;
141 /*Run through parsed errors to check for errors*/
142 typedef Ssl::CertValidationResponse::RecvdErrors::const_iterator SVCRECI
;
143 for (SVCRECI i
= resp
.errors
.begin(); i
!= resp
.errors
.end(); ++i
) {
144 if (i
->error_no
== SSL_ERROR_NONE
) {
145 debugs(83, DBG_IMPORTANT
, "WARNING: cert validator incomplete response: Missing error name from error_id: " << i
->id
);
154 Ssl::CertValidationMsg::getCertByName(std::vector
<CertItem
> const &certs
, std::string
const & name
)
156 typedef std::vector
<CertItem
>::const_iterator SVCI
;
157 for (SVCI ci
= certs
.begin(); ci
!= certs
.end(); ++ci
) {
158 if (ci
->name
.compare(name
) == 0)
159 return ci
->cert
.get();
164 Ssl::CertValidationResponse::RecvdError
&
165 Ssl::CertValidationResponse::getError(int errorId
)
167 typedef Ssl::CertValidationResponse::RecvdErrors::iterator SVCREI
;
168 for (SVCREI i
= errors
.begin(); i
!= errors
.end(); ++i
) {
169 if (i
->id
== errorId
)
172 Ssl::CertValidationResponse::RecvdError errItem
;
173 errItem
.id
= errorId
;
174 errors
.push_back(errItem
);
175 return errors
.back();
178 Ssl::CertValidationResponse::RecvdError::RecvdError(const RecvdError
&old
)
181 error_no
= old
.error_no
;
182 error_reason
= old
.error_reason
;
183 setCert(old
.cert
.get());
186 Ssl::CertValidationResponse::RecvdError
& Ssl::CertValidationResponse::RecvdError::operator = (const RecvdError
&old
)
189 error_no
= old
.error_no
;
190 error_reason
= old
.error_reason
;
191 setCert(old
.cert
.get());
196 Ssl::CertValidationResponse::RecvdError::setCert(X509
*aCert
)
198 cert
.resetAndLock(aCert
);
201 Ssl::CertValidationMsg::CertItem::CertItem(const CertItem
&old
)
204 setCert(old
.cert
.get());
207 Ssl::CertValidationMsg::CertItem
& Ssl::CertValidationMsg::CertItem::operator = (const CertItem
&old
)
210 setCert(old
.cert
.get());
215 Ssl::CertValidationMsg::CertItem::setCert(X509
*aCert
)
217 cert
.resetAndLock(aCert
);
220 const std::string
Ssl::CertValidationMsg::code_cert_validate("cert_validate");
221 const std::string
Ssl::CertValidationMsg::param_domain("domain");
222 const std::string
Ssl::CertValidationMsg::param_cert("cert_");
223 const std::string
Ssl::CertValidationMsg::param_error_name("error_name_");
224 const std::string
Ssl::CertValidationMsg::param_error_reason("error_reason_");
225 const std::string
Ssl::CertValidationMsg::param_error_cert("error_cert_");