WvStreams
wvocsp.cc
1 #include "wvocsp.h"
2 #include "wvsslhacks.h"
3 
4 static const int OCSP_MAX_VALIDITY_PERIOD = (5 * 60); // 5 min: openssl default
5 
6 
7 WvOCSPReq::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 
22 WvOCSPReq::~WvOCSPReq()
23 {
24  if (req)
25  OCSP_REQUEST_free(req);
26 
27  wvssl_free();
28 }
29 
30 
31 void 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 
46 WvOCSPResp::WvOCSPResp() :
47  resp(NULL),
48  bs(NULL),
49  log("OCSP Response", WvLog::Debug5)
50 {
51  wvssl_init();
52 }
53 
54 
55 WvOCSPResp::~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 
67 void 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 
83 bool 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 
99 bool 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 
119 bool 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 
133 WvX509 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 
148 WvOCSPResp::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 
189 WvString 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 }
WvBufBaseCommonImpl::get
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
WvX509
X509 Class to handle certificates and their related functions.
Definition: wvx509.h:41
WvX509::isok
virtual bool isok() const
Is the certificate object valid?
Definition: wvx509.cc:1285
WvString
WvString is an implementation of a simple and efficient printable-string class.
Definition: wvstring.h:329
WvLog
A WvLog stream accepts log messages from applications and forwards them to all registered WvLogRcv's.
Definition: wvlog.h:56
WvOCSPReq
Definition: wvocsp.h:23
WvBufBase< unsigned char >
Specialization of WvBufBase for unsigned char type buffers intended for use with raw memory buffers.
Definition: wvbuf.h:22
WvBufBaseCommonImpl::used
size_t used() const
Returns the number of elements in the buffer currently available for reading.
Definition: wvbufbase.h:92