WvStreams
wvocsp.cc
1#include "wvocsp.h"
2#include "wvsslhacks.h"
3
4static const int OCSP_MAX_VALIDITY_PERIOD = (5 * 60); // 5 min: openssl default
5
6
7WvOCSPReq::WvOCSPReq(const WvX509 &cert, const WvX509 &issuer)
8{
9 wvssl_init();
10
11 req = OCSP_REQUEST_new();
12 assert(req);
13
14 if (cert.isok() && issuer.isok())
15 {
16 id = OCSP_cert_to_id(NULL, cert.cert, issuer.cert);
17 OCSP_request_add0_id(req, id);
18 }
19}
20
21
22WvOCSPReq::~WvOCSPReq()
23{
24 if (req)
25 OCSP_REQUEST_free(req);
26
27 wvssl_free();
28}
29
30
31void WvOCSPReq::encode(WvBuf &buf)
32{
33 BIO *bufbio = BIO_new(BIO_s_mem());
34 assert(bufbio);
35 BUF_MEM *bm;
36
37 // there is no reason why the following should fail, except for OOM
38 assert(wv_i2d_OCSP_REQUEST_bio(bufbio, req) > 0);
39
40 BIO_get_mem_ptr(bufbio, &bm);
41 buf.put(bm->data, bm->length);
42 BIO_free(bufbio);
43}
44
45
46WvOCSPResp::WvOCSPResp() :
47 resp(NULL),
48 bs(NULL),
49 log("OCSP Response", WvLog::Debug5)
50{
51 wvssl_init();
52}
53
54
55WvOCSPResp::~WvOCSPResp()
56{
57 if (bs)
58 OCSP_BASICRESP_free(bs);
59
60 if (resp)
61 OCSP_RESPONSE_free(resp);
62
63 wvssl_free();
64}
65
66
67void WvOCSPResp::decode(WvBuf &encoded)
68{
69 BIO *membuf = BIO_new(BIO_s_mem());
70 BIO_write(membuf, encoded.get(encoded.used()), encoded.used());
71
72 resp = d2i_OCSP_RESPONSE_bio(membuf, NULL);
73
74 if (resp)
75 bs = OCSP_response_get1_basic(resp);
76 else
77 log("Failed to decode response.\n");
78
79 BIO_free_all(membuf);
80}
81
82
83bool WvOCSPResp::isok() const
84{
85 if (!resp)
86 return false;
87
88 int i = OCSP_response_status(resp);
89 if (i != OCSP_RESPONSE_STATUS_SUCCESSFUL)
90 {
91 log("Status not successful: %s\n", wvssl_errstr());
92 return false;
93 }
94
95 return true;
96}
97
98
99bool WvOCSPResp::check_nonce(const WvOCSPReq &req) const
100{
101 if (!bs)
102 return false;
103
104 int i;
105 if ((i = OCSP_check_nonce(req.req, bs)) <= 0)
106 {
107 if (i == -1)
108 log("No nonce in response\n");
109 else
110 log("Nonce verify error\n");
111
112 return false;
113 }
114
115 return true;
116}
117
118
119bool WvOCSPResp::signedbycert(const WvX509 &cert) const
120{
121 STACK_OF(X509) *sk = sk_X509_new_null();
122 sk_X509_push(sk, cert.cert);
123 int i = OCSP_basic_verify(bs, sk, NULL, OCSP_NOVERIFY);
124 sk_X509_free(sk);
125
126 if(i > 0)
127 return true;
128
129 return false;
130}
131
132
133WvX509 WvOCSPResp::get_signing_cert() const
134{
135 const STACK_OF(X509) *certs = OCSP_resp_get0_certs(bs);
136 if (!bs || !sk_X509_num(certs))
137 return WvX509();
138
139 X509 *signer = NULL;
140 if (OCSP_resp_get0_signer(bs, &signer, NULL) == 1) {
141 return WvX509(X509_dup(signer));
142 }
143
144 return WvX509();
145}
146
147
148WvOCSPResp::Status WvOCSPResp::get_status(const WvX509 &cert,
149 const WvX509 &issuer) const
150{
151 if (!isok())
152 return Error;
153
154 if (!cert.isok() && !issuer.isok())
155 return Error;
156
157 int status, reason;
158 ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
159
160 OCSP_CERTID *id = OCSP_cert_to_id(NULL, cert.cert, issuer.cert);
161 assert(id); // only fails in case of OOM
162
163 if(!OCSP_resp_find_status(bs, id, &status, &reason,
164 &rev, &thisupd, &nextupd))
165 {
166 log("OCSP Find Status Error: %s\n", wvssl_errstr());
167 OCSP_CERTID_free(id);
168 return Error;
169 }
170 OCSP_CERTID_free(id);
171
172 if (!OCSP_check_validity(thisupd, nextupd, OCSP_MAX_VALIDITY_PERIOD, -1))
173 {
174 log("Error checking for OCSP validity: %s\n", wvssl_errstr());
175 return Error;
176 }
177
178 if (status == V_OCSP_CERTSTATUS_GOOD)
179 return Good;
180 else if (status == V_OCSP_CERTSTATUS_REVOKED)
181 return Revoked;
182
183 log("OCSP cert status is %s, marking as 'Unknown'.\n",
184 OCSP_cert_status_str(status));
185
186 return Unknown;
187}
188
189WvString WvOCSPResp::status_str(WvOCSPResp::Status status)
190{
191 if (status == Good)
192 return "good";
193 else if (status == Error)
194 return "error";
195 else if (status == Revoked)
196 return "revoked";
197
198 return "unknown";
199}
const T * get(size_t count)
Reads exactly the specified number of elements and returns a pointer to a storage location owned by t...
Definition: wvbufbase.h:114
size_t used() const
Returns the number of elements in the buffer currently available for reading.
Definition: wvbufbase.h:92
Specialization of WvBufBase for unsigned char type buffers intended for use with raw memory buffers.
Definition: wvbuf.h:24
A WvLog stream accepts log messages from applications and forwards them to all registered WvLogRcv's.
Definition: wvlog.h:57
WvString is an implementation of a simple and efficient printable-string class.
Definition: wvstring.h:330
X509 Class to handle certificates and their related functions.
Definition: wvx509.h:42
virtual bool isok() const
Is the certificate object valid?
Definition: wvx509.cc:1285