@@ -46,6 +46,8 @@ using namespace std;
4646 * Initialize OCSP certificate validator.
4747 */
4848OCSP::OCSP (const X509Cert &cert, const X509Cert &issuer, const std::string &userAgent)
49+ : resp(nullptr , OCSP_RESPONSE_free)
50+ , basic(nullptr , OCSP_BASICRESP_free)
4951{
5052 if (!cert)
5153 THROW (" Can not check X.509 certificate, certificate is NULL pointer." );
@@ -56,7 +58,7 @@ OCSP::OCSP(const X509Cert &cert, const X509Cert &issuer, const std::string &user
5658 if (url.empty ())
5759 {
5860 STACK_OF (OPENSSL_STRING) *urls = X509_get1_ocsp (cert.handle ());
59- if (sk_OPENSSL_STRING_num (urls) > 0 )
61+ if (urls && sk_OPENSSL_STRING_num (urls) > 0 )
6062 url = sk_OPENSSL_STRING_value (urls, 0 );
6163 X509_email_free (urls);
6264 }
@@ -90,8 +92,8 @@ OCSP::OCSP(const X509Cert &cert, const X509Cert &issuer, const std::string &user
9092 THROW (" OCSP service responded - Forbidden" );
9193 if (!result)
9294 THROW (" Failed to send OCSP request" );
93- const unsigned char *p2 = (const unsigned char *)result.content .c_str ();
94- resp.reset (d2i_OCSP_RESPONSE (nullptr , &p2, long (result.content .size ())), OCSP_RESPONSE_free );
95+ const auto *p2 = (const unsigned char *)result.content .c_str ();
96+ resp.reset (d2i_OCSP_RESPONSE (nullptr , &p2, long (result.content .size ())));
9597
9698 switch (int respStatus = OCSP_response_status (resp.get ()))
9799 {
@@ -106,7 +108,7 @@ OCSP::OCSP(const X509Cert &cert, const X509Cert &issuer, const std::string &user
106108 THROW (" OCSP request failed, response status: %s" , OCSP_response_status_str (respStatus));
107109 }
108110
109- basic.reset (OCSP_response_get1_basic (resp.get ()), OCSP_BASICRESP_free );
111+ basic.reset (OCSP_response_get1_basic (resp.get ()));
110112 if (!basic)
111113 THROW (" Incorrect OCSP response." );
112114
@@ -127,12 +129,14 @@ OCSP::OCSP(const X509Cert &cert, const X509Cert &issuer, const std::string &user
127129}
128130
129131OCSP::OCSP (const unsigned char *data, size_t size)
132+ : resp(nullptr , OCSP_RESPONSE_free)
133+ , basic(nullptr , OCSP_BASICRESP_free)
130134{
131135 if (size == 0 )
132136 return ;
133- resp.reset (d2i_OCSP_RESPONSE (nullptr , &data, long (size)), OCSP_RESPONSE_free );
137+ resp.reset (d2i_OCSP_RESPONSE (nullptr , &data, long (size)));
134138 if (resp)
135- basic.reset (OCSP_response_get1_basic (resp.get ()), OCSP_BASICRESP_free );
139+ basic.reset (OCSP_response_get1_basic (resp.get ()));
136140}
137141
138142bool OCSP::compareResponderCert (const X509Cert &cert) const
@@ -187,17 +191,19 @@ void OCSP::verifyResponse(const X509Cert &cert) const
187191 THROW (" Failed to verify OCSP response." );
188192
189193 tm tm = producedAt ();
190- time_t t = util::date::mkgmtime (tm);
191- SCOPE (X509_STORE, store, X509CertStore::createStore (X509CertStore::OCSP, &t));
192- STACK_OF (X509) *stack = sk_X509_new_null ();
194+ // Some OCSP-s do not have certificates in response and stack is used for finding certificate for this
195+ auto stack = make_unique_ptr (sk_X509_new_null (), [](auto *sk) { sk_X509_free (sk); });
193196 for (const X509Cert &i: X509CertStore::instance ()->certs (X509CertStore::OCSP))
194197 {
195198 if (compareResponderCert (i))
196- sk_X509_push (stack, i.handle ());
199+ sk_X509_push (stack. get () , i.handle ());
197200 }
198- int result = OCSP_basic_verify (basic.get (), stack, store.get (), OCSP_NOCHECKS);
199- sk_X509_free (stack);
200- if (result != 1 )
201+ auto store = X509CertStore::createStore (X509CertStore::OCSP, tm);
202+ #if OPENSSL_VERSION_NUMBER < 0x30000000L
203+ if (OCSP_basic_verify (basic.get (), stack.get (), store.get (), OCSP_NOCHECKS) != 1 )
204+ #else
205+ if (OCSP_basic_verify (basic.get (), stack.get (), store.get (), OCSP_NOCHECKS | OCSP_PARTIAL_CHAIN) != 1 )
206+ #endif
201207 {
202208 unsigned long err = ERR_get_error ();
203209 if (ERR_GET_LIB (err) == ERR_LIB_OCSP &&
@@ -259,17 +265,18 @@ void OCSP::verifyResponse(const X509Cert &cert) const
259265 */
260266vector<unsigned char > OCSP::nonce () const
261267{
268+ vector<unsigned char > nonce;
262269 if (!basic)
263- return {} ;
270+ return nonce ;
264271 int resp_idx = OCSP_BASICRESP_get_ext_by_NID (basic.get (), NID_id_pkix_OCSP_Nonce, -1 );
265272 if (resp_idx < 0 )
266- return {} ;
273+ return nonce ;
267274 X509_EXTENSION *ext = OCSP_BASICRESP_get_ext (basic.get (), resp_idx);
268275 if (!ext)
269- return {} ;
276+ return nonce ;
270277
271278 ASN1_OCTET_STRING *value = X509_EXTENSION_get_data (ext);
272- vector< unsigned char > nonce (value->data , value->data + value->length );
279+ nonce. assign (value->data , std::next ( value->data , value->length ) );
273280 // OpenSSL OCSP created messages NID_id_pkix_OCSP_Nonce field is DER encoded twice, not a problem with java impl
274281 // XXX: UglyHackTM check if nonceAsn1 contains ASN1_OCTET_STRING
275282 // XXX: if first 2 bytes seem to be beginning of DER ASN1_OCTET_STRING then remove them
@@ -281,9 +288,9 @@ vector<unsigned char> OCSP::nonce() const
281288
282289tm OCSP::producedAt () const
283290{
284- if (!basic)
285- return {};
286291 tm tm {};
292+ if (!basic)
293+ return tm;
287294 ASN1_TIME_to_tm (OCSP_resp_get0_produced_at (basic.get ()), &tm);
288295 return tm;
289296}
0 commit comments