Ruby  2.0.0p247(2013-06-27revision41674)
ext/openssl/ossl_ocsp.c
Go to the documentation of this file.
00001 /*
00002  * $Id: ossl_ocsp.c 31166 2011-03-24 07:29:21Z naruse $
00003  * 'OpenSSL for Ruby' project
00004  * Copyright (C) 2003  Michal Rokos <m.rokos@sh.cvut.cz>
00005  * Copyright (C) 2003  GOTOU Yuuzou <gotoyuzo@notwork.org>
00006  * All rights reserved.
00007  */
00008 /*
00009  * This program is licenced under the same licence as Ruby.
00010  * (See the file 'LICENCE'.)
00011  */
00012 #include "ossl.h"
00013 
00014 #if defined(OSSL_OCSP_ENABLED)
00015 
00016 #define WrapOCSPReq(klass, obj, req) do { \
00017     if(!(req)) ossl_raise(rb_eRuntimeError, "Request wasn't initialized!"); \
00018     (obj) = Data_Wrap_Struct((klass), 0, OCSP_REQUEST_free, (req)); \
00019 } while (0)
00020 #define GetOCSPReq(obj, req) do { \
00021     Data_Get_Struct((obj), OCSP_REQUEST, (req)); \
00022     if(!(req)) ossl_raise(rb_eRuntimeError, "Request wasn't initialized!"); \
00023 } while (0)
00024 #define SafeGetOCSPReq(obj, req) do { \
00025     OSSL_Check_Kind((obj), cOCSPReq); \
00026     GetOCSPReq((obj), (req)); \
00027 } while (0)
00028 
00029 #define WrapOCSPRes(klass, obj, res) do { \
00030     if(!(res)) ossl_raise(rb_eRuntimeError, "Response wasn't initialized!"); \
00031     (obj) = Data_Wrap_Struct((klass), 0, OCSP_RESPONSE_free, (res)); \
00032 } while (0)
00033 #define GetOCSPRes(obj, res) do { \
00034     Data_Get_Struct((obj), OCSP_RESPONSE, (res)); \
00035     if(!(res)) ossl_raise(rb_eRuntimeError, "Response wasn't initialized!"); \
00036 } while (0)
00037 #define SafeGetOCSPRes(obj, res) do { \
00038     OSSL_Check_Kind((obj), cOCSPRes); \
00039     GetOCSPRes((obj), (res)); \
00040 } while (0)
00041 
00042 #define WrapOCSPBasicRes(klass, obj, res) do { \
00043     if(!(res)) ossl_raise(rb_eRuntimeError, "Response wasn't initialized!"); \
00044     (obj) = Data_Wrap_Struct((klass), 0, OCSP_BASICRESP_free, (res)); \
00045 } while (0)
00046 #define GetOCSPBasicRes(obj, res) do { \
00047     Data_Get_Struct((obj), OCSP_BASICRESP, (res)); \
00048     if(!(res)) ossl_raise(rb_eRuntimeError, "Response wasn't initialized!"); \
00049 } while (0)
00050 #define SafeGetOCSPBasicRes(obj, res) do { \
00051     OSSL_Check_Kind((obj), cOCSPBasicRes); \
00052     GetOCSPBasicRes((obj), (res)); \
00053 } while (0)
00054 
00055 #define WrapOCSPCertId(klass, obj, cid) do { \
00056     if(!(cid)) ossl_raise(rb_eRuntimeError, "Cert ID wasn't initialized!"); \
00057     (obj) = Data_Wrap_Struct((klass), 0, OCSP_CERTID_free, (cid)); \
00058 } while (0)
00059 #define GetOCSPCertId(obj, cid) do { \
00060     Data_Get_Struct((obj), OCSP_CERTID, (cid)); \
00061     if(!(cid)) ossl_raise(rb_eRuntimeError, "Cert ID wasn't initialized!"); \
00062 } while (0)
00063 #define SafeGetOCSPCertId(obj, cid) do { \
00064     OSSL_Check_Kind((obj), cOCSPCertId); \
00065     GetOCSPCertId((obj), (cid)); \
00066 } while (0)
00067 
00068 VALUE mOCSP;
00069 VALUE eOCSPError;
00070 VALUE cOCSPReq;
00071 VALUE cOCSPRes;
00072 VALUE cOCSPBasicRes;
00073 VALUE cOCSPCertId;
00074 
00075 /*
00076  * Public
00077  */
00078 static VALUE
00079 ossl_ocspcertid_new(OCSP_CERTID *cid)
00080 {
00081     VALUE obj;
00082     WrapOCSPCertId(cOCSPCertId, obj, cid);
00083     return obj;
00084 }
00085 
00086 /*
00087  * OCSP::Resquest
00088  */
00089 static VALUE
00090 ossl_ocspreq_alloc(VALUE klass)
00091 {
00092     OCSP_REQUEST *req;
00093     VALUE obj;
00094 
00095     if (!(req = OCSP_REQUEST_new()))
00096         ossl_raise(eOCSPError, NULL);
00097     WrapOCSPReq(klass, obj, req);
00098 
00099     return obj;
00100 }
00101 
00102 static VALUE
00103 ossl_ocspreq_initialize(int argc, VALUE *argv, VALUE self)
00104 {
00105     VALUE arg;
00106     const unsigned char *p;
00107 
00108     rb_scan_args(argc, argv, "01", &arg);
00109     if(!NIL_P(arg)){
00110         OCSP_REQUEST *req = DATA_PTR(self), *x;
00111         arg = ossl_to_der_if_possible(arg);
00112         StringValue(arg);
00113         p = (unsigned char*)RSTRING_PTR(arg);
00114         x = d2i_OCSP_REQUEST(&req, &p, RSTRING_LEN(arg));
00115         DATA_PTR(self) = req;
00116         if(!x){
00117             ossl_raise(eOCSPError, "cannot load DER encoded request");
00118         }
00119     }
00120 
00121     return self;
00122 }
00123 
00124 static VALUE
00125 ossl_ocspreq_add_nonce(int argc, VALUE *argv, VALUE self)
00126 {
00127     OCSP_REQUEST *req;
00128     VALUE val;
00129     int ret;
00130 
00131     rb_scan_args(argc, argv, "01", &val);
00132     if(NIL_P(val)) {
00133         GetOCSPReq(self, req);
00134         ret = OCSP_request_add1_nonce(req, NULL, -1);
00135     }
00136     else{
00137         StringValue(val);
00138         GetOCSPReq(self, req);
00139         ret = OCSP_request_add1_nonce(req, (unsigned char *)RSTRING_PTR(val), RSTRING_LENINT(val));
00140     }
00141     if(!ret) ossl_raise(eOCSPError, NULL);
00142 
00143     return self;
00144 }
00145 
00146 /* Check nonce validity in a request and response.
00147  * Return value reflects result:
00148  *  1: nonces present and equal.
00149  *  2: nonces both absent.
00150  *  3: nonce present in response only.
00151  *  0: nonces both present and not equal.
00152  * -1: nonce in request only.
00153  *
00154  *  For most responders clients can check return > 0.
00155  *  If responder doesn't handle nonces return != 0 may be
00156  *  necessary. return == 0 is always an error.
00157  */
00158 static VALUE
00159 ossl_ocspreq_check_nonce(VALUE self, VALUE basic_resp)
00160 {
00161     OCSP_REQUEST *req;
00162     OCSP_BASICRESP *bs;
00163     int res;
00164 
00165     GetOCSPReq(self, req);
00166     SafeGetOCSPBasicRes(basic_resp, bs);
00167     res = OCSP_check_nonce(req, bs);
00168 
00169     return INT2NUM(res);
00170 }
00171 
00172 static VALUE
00173 ossl_ocspreq_add_certid(VALUE self, VALUE certid)
00174 {
00175     OCSP_REQUEST *req;
00176     OCSP_CERTID *id;
00177 
00178     GetOCSPReq(self, req);
00179     GetOCSPCertId(certid, id);
00180     if(!OCSP_request_add0_id(req, OCSP_CERTID_dup(id)))
00181         ossl_raise(eOCSPError, NULL);
00182 
00183     return self;
00184 }
00185 
00186 static VALUE
00187 ossl_ocspreq_get_certid(VALUE self)
00188 {
00189     OCSP_REQUEST *req;
00190     OCSP_ONEREQ *one;
00191     OCSP_CERTID *id;
00192     VALUE ary, tmp;
00193     int i, count;
00194 
00195     GetOCSPReq(self, req);
00196     count = OCSP_request_onereq_count(req);
00197     ary = (count > 0) ? rb_ary_new() : Qnil;
00198     for(i = 0; i < count; i++){
00199         one = OCSP_request_onereq_get0(req, i);
00200         if(!(id = OCSP_CERTID_dup(OCSP_onereq_get0_id(one))))
00201             ossl_raise(eOCSPError, NULL);
00202         WrapOCSPCertId(cOCSPCertId, tmp, id);
00203         rb_ary_push(ary, tmp);
00204     }
00205 
00206     return ary;
00207 }
00208 
00209 static VALUE
00210 ossl_ocspreq_sign(int argc, VALUE *argv, VALUE self)
00211 {
00212     VALUE signer_cert, signer_key, certs, flags;
00213     OCSP_REQUEST *req;
00214     X509 *signer;
00215     EVP_PKEY *key;
00216     STACK_OF(X509) *x509s;
00217     unsigned long flg;
00218     int ret;
00219 
00220     rb_scan_args(argc, argv, "22", &signer_cert, &signer_key, &certs, &flags);
00221     signer = GetX509CertPtr(signer_cert);
00222     key = GetPrivPKeyPtr(signer_key);
00223     flg = NIL_P(flags) ? 0 : NUM2INT(flags);
00224     if(NIL_P(certs)){
00225         x509s = sk_X509_new_null();
00226         flags |= OCSP_NOCERTS;
00227     }
00228     else x509s = ossl_x509_ary2sk(certs);
00229     GetOCSPReq(self, req);
00230     ret = OCSP_request_sign(req, signer, key, EVP_sha1(), x509s, flg);
00231     sk_X509_pop_free(x509s, X509_free);
00232     if(!ret) ossl_raise(eOCSPError, NULL);
00233 
00234     return self;
00235 }
00236 
00237 static VALUE
00238 ossl_ocspreq_verify(int argc, VALUE *argv, VALUE self)
00239 {
00240     VALUE certs, store, flags;
00241     OCSP_REQUEST *req;
00242     STACK_OF(X509) *x509s;
00243     X509_STORE *x509st;
00244     int flg, result;
00245 
00246     rb_scan_args(argc, argv, "21", &certs, &store, &flags);
00247     x509st = GetX509StorePtr(store);
00248     flg = NIL_P(flags) ? 0 : NUM2INT(flags);
00249     x509s = ossl_x509_ary2sk(certs);
00250     GetOCSPReq(self, req);
00251     result = OCSP_request_verify(req, x509s, x509st, flg);
00252     sk_X509_pop_free(x509s, X509_free);
00253     if(!result) rb_warn("%s", ERR_error_string(ERR_peek_error(), NULL));
00254 
00255     return result ? Qtrue : Qfalse;
00256 }
00257 
00258 static VALUE
00259 ossl_ocspreq_to_der(VALUE self)
00260 {
00261     OCSP_REQUEST *req;
00262     VALUE str;
00263     unsigned char *p;
00264     long len;
00265 
00266     GetOCSPReq(self, req);
00267     if((len = i2d_OCSP_REQUEST(req, NULL)) <= 0)
00268         ossl_raise(eOCSPError, NULL);
00269     str = rb_str_new(0, len);
00270     p = (unsigned char *)RSTRING_PTR(str);
00271     if(i2d_OCSP_REQUEST(req, &p) <= 0)
00272         ossl_raise(eOCSPError, NULL);
00273     ossl_str_adjust(str, p);
00274 
00275     return str;
00276 }
00277 
00278 /*
00279  * OCSP::Response
00280  */
00281 static VALUE
00282 ossl_ocspres_s_create(VALUE klass, VALUE status, VALUE basic_resp)
00283 {
00284     OCSP_BASICRESP *bs;
00285     OCSP_RESPONSE *res;
00286     VALUE obj;
00287     int st = NUM2INT(status);
00288 
00289     if(NIL_P(basic_resp)) bs = NULL;
00290     else GetOCSPBasicRes(basic_resp, bs); /* NO NEED TO DUP */
00291     if(!(res = OCSP_response_create(st, bs)))
00292         ossl_raise(eOCSPError, NULL);
00293     WrapOCSPRes(klass, obj, res);
00294 
00295     return obj;
00296 }
00297 
00298 static VALUE
00299 ossl_ocspres_alloc(VALUE klass)
00300 {
00301     OCSP_RESPONSE *res;
00302     VALUE obj;
00303 
00304     if(!(res = OCSP_RESPONSE_new()))
00305         ossl_raise(eOCSPError, NULL);
00306     WrapOCSPRes(klass, obj, res);
00307 
00308     return obj;
00309 }
00310 
00311 static VALUE
00312 ossl_ocspres_initialize(int argc, VALUE *argv, VALUE self)
00313 {
00314     VALUE arg;
00315     const unsigned char *p;
00316 
00317     rb_scan_args(argc, argv, "01", &arg);
00318     if(!NIL_P(arg)){
00319         OCSP_RESPONSE *res = DATA_PTR(self), *x;
00320         arg = ossl_to_der_if_possible(arg);
00321         StringValue(arg);
00322         p = (unsigned char *)RSTRING_PTR(arg);
00323         x = d2i_OCSP_RESPONSE(&res, &p, RSTRING_LEN(arg));
00324         DATA_PTR(self) = res;
00325         if(!x){
00326             ossl_raise(eOCSPError, "cannot load DER encoded response");
00327         }
00328     }
00329 
00330     return self;
00331 }
00332 
00333 static VALUE
00334 ossl_ocspres_status(VALUE self)
00335 {
00336     OCSP_RESPONSE *res;
00337     int st;
00338 
00339     GetOCSPRes(self, res);
00340     st = OCSP_response_status(res);
00341 
00342     return INT2NUM(st);
00343 }
00344 
00345 static VALUE
00346 ossl_ocspres_status_string(VALUE self)
00347 {
00348     OCSP_RESPONSE *res;
00349     int st;
00350 
00351     GetOCSPRes(self, res);
00352     st = OCSP_response_status(res);
00353 
00354     return rb_str_new2(OCSP_response_status_str(st));
00355 }
00356 
00357 static VALUE
00358 ossl_ocspres_get_basic(VALUE self)
00359 {
00360     OCSP_RESPONSE *res;
00361     OCSP_BASICRESP *bs;
00362     VALUE ret;
00363 
00364     GetOCSPRes(self, res);
00365     if(!(bs = OCSP_response_get1_basic(res)))
00366         return Qnil;
00367     WrapOCSPBasicRes(cOCSPBasicRes, ret, bs);
00368 
00369     return ret;
00370 }
00371 
00372 static VALUE
00373 ossl_ocspres_to_der(VALUE self)
00374 {
00375     OCSP_RESPONSE *res;
00376     VALUE str;
00377     long len;
00378     unsigned char *p;
00379 
00380     GetOCSPRes(self, res);
00381     if((len = i2d_OCSP_RESPONSE(res, NULL)) <= 0)
00382         ossl_raise(eOCSPError, NULL);
00383     str = rb_str_new(0, len);
00384     p = (unsigned char *)RSTRING_PTR(str);
00385     if(i2d_OCSP_RESPONSE(res, &p) <= 0)
00386         ossl_raise(eOCSPError, NULL);
00387     ossl_str_adjust(str, p);
00388 
00389     return str;
00390 }
00391 
00392 /*
00393  * OCSP::BasicResponse
00394  */
00395 static VALUE
00396 ossl_ocspbres_alloc(VALUE klass)
00397 {
00398     OCSP_BASICRESP *bs;
00399     VALUE obj;
00400 
00401     if(!(bs = OCSP_BASICRESP_new()))
00402         ossl_raise(eOCSPError, NULL);
00403     WrapOCSPBasicRes(klass, obj, bs);
00404 
00405     return obj;
00406 }
00407 
00408 static VALUE
00409 ossl_ocspbres_initialize(int argc, VALUE *argv, VALUE self)
00410 {
00411     return self;
00412 }
00413 
00414 static VALUE
00415 ossl_ocspbres_copy_nonce(VALUE self, VALUE request)
00416 {
00417     OCSP_BASICRESP *bs;
00418     OCSP_REQUEST *req;
00419     int ret;
00420 
00421     GetOCSPBasicRes(self, bs);
00422     SafeGetOCSPReq(request, req);
00423     ret = OCSP_copy_nonce(bs, req);
00424 
00425     return INT2NUM(ret);
00426 }
00427 
00428 static VALUE
00429 ossl_ocspbres_add_nonce(int argc, VALUE *argv, VALUE self)
00430 {
00431     OCSP_BASICRESP *bs;
00432     VALUE val;
00433     int ret;
00434 
00435     rb_scan_args(argc, argv, "01", &val);
00436     if(NIL_P(val)) {
00437         GetOCSPBasicRes(self, bs);
00438         ret = OCSP_basic_add1_nonce(bs, NULL, -1);
00439     }
00440     else{
00441         StringValue(val);
00442         GetOCSPBasicRes(self, bs);
00443         ret = OCSP_basic_add1_nonce(bs, (unsigned char *)RSTRING_PTR(val), RSTRING_LENINT(val));
00444     }
00445     if(!ret) ossl_raise(eOCSPError, NULL);
00446 
00447     return self;
00448 }
00449 
00450 static VALUE
00451 ossl_ocspbres_add_status(VALUE self, VALUE cid, VALUE status,
00452                          VALUE reason, VALUE revtime,
00453                          VALUE thisupd, VALUE nextupd, VALUE ext)
00454 {
00455     OCSP_BASICRESP *bs;
00456     OCSP_SINGLERESP *single;
00457     OCSP_CERTID *id;
00458     int st, rsn;
00459     ASN1_TIME *ths, *nxt, *rev;
00460     int error, i, rstatus = 0;
00461     VALUE tmp;
00462 
00463     st = NUM2INT(status);
00464     rsn = NIL_P(status) ? 0 : NUM2INT(reason);
00465     if(!NIL_P(ext)){
00466         /* All ary's members should be X509Extension */
00467         Check_Type(ext, T_ARRAY);
00468         for (i = 0; i < RARRAY_LEN(ext); i++)
00469             OSSL_Check_Kind(RARRAY_PTR(ext)[i], cX509Ext);
00470     }
00471 
00472     error = 0;
00473     ths = nxt = rev = NULL;
00474     if(!NIL_P(revtime)){
00475         tmp = rb_protect(rb_Integer, revtime, &rstatus);
00476         if(rstatus) goto err;
00477         rev = X509_gmtime_adj(NULL, NUM2INT(tmp));
00478     }
00479     tmp = rb_protect(rb_Integer, thisupd, &rstatus);
00480     if(rstatus) goto err;
00481     ths = X509_gmtime_adj(NULL, NUM2INT(tmp));
00482     tmp = rb_protect(rb_Integer, nextupd, &rstatus);
00483     if(rstatus) goto err;
00484     nxt = X509_gmtime_adj(NULL, NUM2INT(tmp));
00485 
00486     GetOCSPBasicRes(self, bs);
00487     SafeGetOCSPCertId(cid, id);
00488     if(!(single = OCSP_basic_add1_status(bs, id, st, rsn, rev, ths, nxt))){
00489         error = 1;
00490         goto err;
00491     }
00492 
00493     if(!NIL_P(ext)){
00494         X509_EXTENSION *x509ext;
00495         sk_X509_EXTENSION_pop_free(single->singleExtensions, X509_EXTENSION_free);
00496         single->singleExtensions = NULL;
00497         for(i = 0; i < RARRAY_LEN(ext); i++){
00498             x509ext = DupX509ExtPtr(RARRAY_PTR(ext)[i]);
00499             if(!OCSP_SINGLERESP_add_ext(single, x509ext, -1)){
00500                 X509_EXTENSION_free(x509ext);
00501                 error = 1;
00502                 goto err;
00503             }
00504             X509_EXTENSION_free(x509ext);
00505         }
00506     }
00507 
00508  err:
00509     ASN1_TIME_free(ths);
00510     ASN1_TIME_free(nxt);
00511     ASN1_TIME_free(rev);
00512     if(error) ossl_raise(eOCSPError, NULL);
00513     if(rstatus) rb_jump_tag(rstatus);
00514 
00515     return self;
00516 }
00517 
00518 static VALUE
00519 ossl_ocspbres_get_status(VALUE self)
00520 {
00521     OCSP_BASICRESP *bs;
00522     OCSP_SINGLERESP *single;
00523     OCSP_CERTID *cid;
00524     ASN1_TIME *revtime, *thisupd, *nextupd;
00525     int status, reason;
00526     X509_EXTENSION *x509ext;
00527     VALUE ret, ary, ext;
00528     int count, ext_count, i, j;
00529 
00530     GetOCSPBasicRes(self, bs);
00531     ret = rb_ary_new();
00532     count = OCSP_resp_count(bs);
00533     for(i = 0; i < count; i++){
00534         single = OCSP_resp_get0(bs, i);
00535         if(!single) continue;
00536 
00537         revtime = thisupd = nextupd = NULL;
00538         status = OCSP_single_get0_status(single, &reason, &revtime,
00539                                          &thisupd, &nextupd);
00540         if(status < 0) continue;
00541         if(!(cid = OCSP_CERTID_dup(single->certId)))
00542             ossl_raise(eOCSPError, NULL);
00543         ary = rb_ary_new();
00544         rb_ary_push(ary, ossl_ocspcertid_new(cid));
00545         rb_ary_push(ary, INT2NUM(status));
00546         rb_ary_push(ary, INT2NUM(reason));
00547         rb_ary_push(ary, revtime ? asn1time_to_time(revtime) : Qnil);
00548         rb_ary_push(ary, thisupd ? asn1time_to_time(thisupd) : Qnil);
00549         rb_ary_push(ary, nextupd ? asn1time_to_time(nextupd) : Qnil);
00550         ext = rb_ary_new();
00551         ext_count = OCSP_SINGLERESP_get_ext_count(single);
00552         for(j = 0; j < ext_count; j++){
00553             x509ext = OCSP_SINGLERESP_get_ext(single, j);
00554             rb_ary_push(ext, ossl_x509ext_new(x509ext));
00555         }
00556         rb_ary_push(ary, ext);
00557         rb_ary_push(ret, ary);
00558     }
00559 
00560     return ret;
00561 }
00562 
00563 static VALUE
00564 ossl_ocspbres_sign(int argc, VALUE *argv, VALUE self)
00565 {
00566     VALUE signer_cert, signer_key, certs, flags;
00567     OCSP_BASICRESP *bs;
00568     X509 *signer;
00569     EVP_PKEY *key;
00570     STACK_OF(X509) *x509s;
00571     unsigned long flg;
00572     int ret;
00573 
00574     rb_scan_args(argc, argv, "22", &signer_cert, &signer_key, &certs, &flags);
00575     signer = GetX509CertPtr(signer_cert);
00576     key = GetPrivPKeyPtr(signer_key);
00577     flg = NIL_P(flags) ? 0 : NUM2INT(flags);
00578     if(NIL_P(certs)){
00579         x509s = sk_X509_new_null();
00580         flg |= OCSP_NOCERTS;
00581     }
00582     else{
00583         x509s = ossl_x509_ary2sk(certs);
00584     }
00585     GetOCSPBasicRes(self, bs);
00586     ret = OCSP_basic_sign(bs, signer, key, EVP_sha1(), x509s, flg);
00587     sk_X509_pop_free(x509s, X509_free);
00588     if(!ret) ossl_raise(eOCSPError, NULL);
00589 
00590     return self;
00591 }
00592 
00593 static VALUE
00594 ossl_ocspbres_verify(int argc, VALUE *argv, VALUE self)
00595 {
00596     VALUE certs, store, flags, result;
00597     OCSP_BASICRESP *bs;
00598     STACK_OF(X509) *x509s;
00599     X509_STORE *x509st;
00600     int flg;
00601 
00602     rb_scan_args(argc, argv, "21", &certs, &store, &flags);
00603     x509st = GetX509StorePtr(store);
00604     flg = NIL_P(flags) ? 0 : NUM2INT(flags);
00605     x509s = ossl_x509_ary2sk(certs);
00606     GetOCSPBasicRes(self, bs);
00607     result = OCSP_basic_verify(bs, x509s, x509st, flg) > 0 ? Qtrue : Qfalse;
00608     sk_X509_pop_free(x509s, X509_free);
00609     if(!result) rb_warn("%s", ERR_error_string(ERR_peek_error(), NULL));
00610 
00611     return result;
00612 }
00613 
00614 /*
00615  * OCSP::CertificateId
00616  */
00617 static VALUE
00618 ossl_ocspcid_alloc(VALUE klass)
00619 {
00620     OCSP_CERTID *id;
00621     VALUE obj;
00622 
00623     if(!(id = OCSP_CERTID_new()))
00624         ossl_raise(eOCSPError, NULL);
00625     WrapOCSPCertId(klass, obj, id);
00626 
00627     return obj;
00628 }
00629 
00630 static VALUE
00631 ossl_ocspcid_initialize(int argc, VALUE *argv, VALUE self)
00632 {
00633     OCSP_CERTID *id, *newid;
00634     X509 *x509s, *x509i;
00635     VALUE subject, issuer, digest;
00636     const EVP_MD *md;
00637 
00638     if (rb_scan_args(argc, argv, "21", &subject, &issuer, &digest) == 0) {
00639         return self;
00640     }
00641 
00642     x509s = GetX509CertPtr(subject); /* NO NEED TO DUP */
00643     x509i = GetX509CertPtr(issuer); /* NO NEED TO DUP */
00644 
00645     if (!NIL_P(digest)) {
00646         md = GetDigestPtr(digest);
00647         newid = OCSP_cert_to_id(md, x509s, x509i);
00648     } else {
00649         newid = OCSP_cert_to_id(NULL, x509s, x509i);
00650     }
00651     if(!newid)
00652         ossl_raise(eOCSPError, NULL);
00653     GetOCSPCertId(self, id);
00654     OCSP_CERTID_free(id);
00655     RDATA(self)->data = newid;
00656 
00657     return self;
00658 }
00659 
00660 static VALUE
00661 ossl_ocspcid_cmp(VALUE self, VALUE other)
00662 {
00663     OCSP_CERTID *id, *id2;
00664     int result;
00665 
00666     GetOCSPCertId(self, id);
00667     SafeGetOCSPCertId(other, id2);
00668     result = OCSP_id_cmp(id, id2);
00669 
00670     return (result == 0) ? Qtrue : Qfalse;
00671 }
00672 
00673 static VALUE
00674 ossl_ocspcid_cmp_issuer(VALUE self, VALUE other)
00675 {
00676     OCSP_CERTID *id, *id2;
00677     int result;
00678 
00679     GetOCSPCertId(self, id);
00680     SafeGetOCSPCertId(other, id2);
00681     result = OCSP_id_issuer_cmp(id, id2);
00682 
00683     return (result == 0) ? Qtrue : Qfalse;
00684 }
00685 
00686 static VALUE
00687 ossl_ocspcid_get_serial(VALUE self)
00688 {
00689     OCSP_CERTID *id;
00690 
00691     GetOCSPCertId(self, id);
00692 
00693     return asn1integer_to_num(id->serialNumber);
00694 }
00695 
00696 void
00697 Init_ossl_ocsp()
00698 {
00699     mOCSP = rb_define_module_under(mOSSL, "OCSP");
00700 
00701     eOCSPError = rb_define_class_under(mOCSP, "OCSPError", eOSSLError);
00702 
00703     cOCSPReq = rb_define_class_under(mOCSP, "Request", rb_cObject);
00704     rb_define_alloc_func(cOCSPReq, ossl_ocspreq_alloc);
00705     rb_define_method(cOCSPReq, "initialize", ossl_ocspreq_initialize, -1);
00706     rb_define_method(cOCSPReq, "add_nonce", ossl_ocspreq_add_nonce, -1);
00707     rb_define_method(cOCSPReq, "check_nonce", ossl_ocspreq_check_nonce, 1);
00708     rb_define_method(cOCSPReq, "add_certid", ossl_ocspreq_add_certid, 1);
00709     rb_define_method(cOCSPReq, "certid", ossl_ocspreq_get_certid, 0);
00710     rb_define_method(cOCSPReq, "sign", ossl_ocspreq_sign, -1);
00711     rb_define_method(cOCSPReq, "verify", ossl_ocspreq_verify, -1);
00712     rb_define_method(cOCSPReq, "to_der", ossl_ocspreq_to_der, 0);
00713 
00714     cOCSPRes = rb_define_class_under(mOCSP, "Response", rb_cObject);
00715     rb_define_singleton_method(cOCSPRes, "create", ossl_ocspres_s_create, 2);
00716     rb_define_alloc_func(cOCSPRes, ossl_ocspres_alloc);
00717     rb_define_method(cOCSPRes, "initialize", ossl_ocspres_initialize, -1);
00718     rb_define_method(cOCSPRes, "status", ossl_ocspres_status, 0);
00719     rb_define_method(cOCSPRes, "status_string", ossl_ocspres_status_string, 0);
00720     rb_define_method(cOCSPRes, "basic", ossl_ocspres_get_basic, 0);
00721     rb_define_method(cOCSPRes, "to_der", ossl_ocspres_to_der, 0);
00722 
00723     cOCSPBasicRes = rb_define_class_under(mOCSP, "BasicResponse", rb_cObject);
00724     rb_define_alloc_func(cOCSPBasicRes, ossl_ocspbres_alloc);
00725     rb_define_method(cOCSPBasicRes, "initialize", ossl_ocspbres_initialize, -1);
00726     rb_define_method(cOCSPBasicRes, "copy_nonce", ossl_ocspbres_copy_nonce, 1);
00727     rb_define_method(cOCSPBasicRes, "add_nonce", ossl_ocspbres_add_nonce, -1);
00728     rb_define_method(cOCSPBasicRes, "add_status", ossl_ocspbres_add_status, 7);
00729     rb_define_method(cOCSPBasicRes, "status", ossl_ocspbres_get_status, 0);
00730     rb_define_method(cOCSPBasicRes, "sign", ossl_ocspbres_sign, -1);
00731     rb_define_method(cOCSPBasicRes, "verify", ossl_ocspbres_verify, -1);
00732 
00733     cOCSPCertId = rb_define_class_under(mOCSP, "CertificateId", rb_cObject);
00734     rb_define_alloc_func(cOCSPCertId, ossl_ocspcid_alloc);
00735     rb_define_method(cOCSPCertId, "initialize", ossl_ocspcid_initialize, -1);
00736     rb_define_method(cOCSPCertId, "cmp", ossl_ocspcid_cmp, 1);
00737     rb_define_method(cOCSPCertId, "cmp_issuer", ossl_ocspcid_cmp_issuer, 1);
00738     rb_define_method(cOCSPCertId, "serial", ossl_ocspcid_get_serial, 0);
00739 
00740 #define DefOCSPConst(x) rb_define_const(mOCSP, #x, INT2NUM(OCSP_##x))
00741 
00742     DefOCSPConst(RESPONSE_STATUS_SUCCESSFUL);
00743     DefOCSPConst(RESPONSE_STATUS_MALFORMEDREQUEST);
00744     DefOCSPConst(RESPONSE_STATUS_INTERNALERROR);
00745     DefOCSPConst(RESPONSE_STATUS_TRYLATER);
00746     DefOCSPConst(RESPONSE_STATUS_SIGREQUIRED);
00747     DefOCSPConst(RESPONSE_STATUS_UNAUTHORIZED);
00748 
00749     DefOCSPConst(REVOKED_STATUS_NOSTATUS);
00750     DefOCSPConst(REVOKED_STATUS_UNSPECIFIED);
00751     DefOCSPConst(REVOKED_STATUS_KEYCOMPROMISE);
00752     DefOCSPConst(REVOKED_STATUS_CACOMPROMISE);
00753     DefOCSPConst(REVOKED_STATUS_AFFILIATIONCHANGED);
00754     DefOCSPConst(REVOKED_STATUS_SUPERSEDED);
00755     DefOCSPConst(REVOKED_STATUS_CESSATIONOFOPERATION);
00756     DefOCSPConst(REVOKED_STATUS_CERTIFICATEHOLD);
00757     DefOCSPConst(REVOKED_STATUS_REMOVEFROMCRL);
00758 
00759     DefOCSPConst(NOCERTS);
00760     DefOCSPConst(NOINTERN);
00761     DefOCSPConst(NOSIGS);
00762     DefOCSPConst(NOCHAIN);
00763     DefOCSPConst(NOVERIFY);
00764     DefOCSPConst(NOEXPLICIT);
00765     DefOCSPConst(NOCASIGN);
00766     DefOCSPConst(NODELEGATED);
00767     DefOCSPConst(NOCHECKS);
00768     DefOCSPConst(TRUSTOTHER);
00769     DefOCSPConst(RESPID_KEY);
00770     DefOCSPConst(NOTIME);
00771 
00772 #define DefOCSPVConst(x) rb_define_const(mOCSP, "V_" #x, INT2NUM(V_OCSP_##x))
00773 
00774     DefOCSPVConst(CERTSTATUS_GOOD);
00775     DefOCSPVConst(CERTSTATUS_REVOKED);
00776     DefOCSPVConst(CERTSTATUS_UNKNOWN);
00777     DefOCSPVConst(RESPID_NAME);
00778     DefOCSPVConst(RESPID_KEY);
00779 }
00780 
00781 #else /* ! OSSL_OCSP_ENABLED */
00782 void
00783 Init_ossl_ocsp()
00784 {
00785 }
00786 #endif
00787