diff options
Diffstat (limited to 'ruby_2_2/ext/openssl/ossl_ocsp.c')
-rw-r--r-- | ruby_2_2/ext/openssl/ossl_ocsp.c | 1244 |
1 files changed, 0 insertions, 1244 deletions
diff --git a/ruby_2_2/ext/openssl/ossl_ocsp.c b/ruby_2_2/ext/openssl/ossl_ocsp.c deleted file mode 100644 index dc31d79cf7..0000000000 --- a/ruby_2_2/ext/openssl/ossl_ocsp.c +++ /dev/null @@ -1,1244 +0,0 @@ -/* - * $Id$ - * 'OpenSSL for Ruby' project - * Copyright (C) 2003 Michal Rokos <m.rokos@sh.cvut.cz> - * Copyright (C) 2003 GOTOU Yuuzou <gotoyuzo@notwork.org> - * All rights reserved. - */ -/* - * This program is licenced under the same licence as Ruby. - * (See the file 'LICENCE'.) - */ -#include "ossl.h" - -#if defined(OSSL_OCSP_ENABLED) - -#define WrapOCSPReq(klass, obj, req) do { \ - if(!(req)) ossl_raise(rb_eRuntimeError, "Request wasn't initialized!"); \ - (obj) = TypedData_Wrap_Struct((klass), &ossl_ocsp_request_type, (req)); \ -} while (0) -#define GetOCSPReq(obj, req) do { \ - TypedData_Get_Struct((obj), OCSP_REQUEST, &ossl_ocsp_request_type, (req)); \ - if(!(req)) ossl_raise(rb_eRuntimeError, "Request wasn't initialized!"); \ -} while (0) -#define SafeGetOCSPReq(obj, req) do { \ - OSSL_Check_Kind((obj), cOCSPReq); \ - GetOCSPReq((obj), (req)); \ -} while (0) - -#define WrapOCSPRes(klass, obj, res) do { \ - if(!(res)) ossl_raise(rb_eRuntimeError, "Response wasn't initialized!"); \ - (obj) = TypedData_Wrap_Struct((klass), &ossl_ocsp_response_type, (res)); \ -} while (0) -#define GetOCSPRes(obj, res) do { \ - TypedData_Get_Struct((obj), OCSP_RESPONSE, &ossl_ocsp_response_type, (res)); \ - if(!(res)) ossl_raise(rb_eRuntimeError, "Response wasn't initialized!"); \ -} while (0) -#define SafeGetOCSPRes(obj, res) do { \ - OSSL_Check_Kind((obj), cOCSPRes); \ - GetOCSPRes((obj), (res)); \ -} while (0) - -#define WrapOCSPBasicRes(klass, obj, res) do { \ - if(!(res)) ossl_raise(rb_eRuntimeError, "Response wasn't initialized!"); \ - (obj) = TypedData_Wrap_Struct((klass), &ossl_ocsp_basicresp_type, (res)); \ -} while (0) -#define GetOCSPBasicRes(obj, res) do { \ - TypedData_Get_Struct((obj), OCSP_BASICRESP, &ossl_ocsp_basicresp_type, (res)); \ - if(!(res)) ossl_raise(rb_eRuntimeError, "Response wasn't initialized!"); \ -} while (0) -#define SafeGetOCSPBasicRes(obj, res) do { \ - OSSL_Check_Kind((obj), cOCSPBasicRes); \ - GetOCSPBasicRes((obj), (res)); \ -} while (0) - -#define WrapOCSPCertId(klass, obj, cid) do { \ - if(!(cid)) ossl_raise(rb_eRuntimeError, "Cert ID wasn't initialized!"); \ - (obj) = TypedData_Wrap_Struct((klass), &ossl_ocsp_certid_type, (cid)); \ -} while (0) -#define GetOCSPCertId(obj, cid) do { \ - TypedData_Get_Struct((obj), OCSP_CERTID, &ossl_ocsp_certid_type, (cid)); \ - if(!(cid)) ossl_raise(rb_eRuntimeError, "Cert ID wasn't initialized!"); \ -} while (0) -#define SafeGetOCSPCertId(obj, cid) do { \ - OSSL_Check_Kind((obj), cOCSPCertId); \ - GetOCSPCertId((obj), (cid)); \ -} while (0) - -VALUE mOCSP; -VALUE eOCSPError; -VALUE cOCSPReq; -VALUE cOCSPRes; -VALUE cOCSPBasicRes; -VALUE cOCSPCertId; - -static void -ossl_ocsp_request_free(void *ptr) -{ - OCSP_REQUEST_free(ptr); -} - -static const rb_data_type_t ossl_ocsp_request_type = { - "OpenSSL/OCSP/REQUEST", - { - 0, ossl_ocsp_request_free, - }, - 0, 0, RUBY_TYPED_FREE_IMMEDIATELY, -}; - -static void -ossl_ocsp_response_free(void *ptr) -{ - OCSP_RESPONSE_free(ptr); -} - -static const rb_data_type_t ossl_ocsp_response_type = { - "OpenSSL/OCSP/RESPONSE", - { - 0, ossl_ocsp_response_free, - }, - 0, 0, RUBY_TYPED_FREE_IMMEDIATELY, -}; - -static void -ossl_ocsp_basicresp_free(void *ptr) -{ - OCSP_BASICRESP_free(ptr); -} - -static const rb_data_type_t ossl_ocsp_basicresp_type = { - "OpenSSL/OCSP/BASICRESP", - { - 0, ossl_ocsp_basicresp_free, - }, - 0, 0, RUBY_TYPED_FREE_IMMEDIATELY, -}; - -static void -ossl_ocsp_certid_free(void *ptr) -{ - OCSP_CERTID_free(ptr); -} - -static const rb_data_type_t ossl_ocsp_certid_type = { - "OpenSSL/OCSP/CERTID", - { - 0, ossl_ocsp_certid_free, - }, - 0, 0, RUBY_TYPED_FREE_IMMEDIATELY, -}; - -/* - * Public - */ -static VALUE -ossl_ocspcertid_new(OCSP_CERTID *cid) -{ - VALUE obj; - WrapOCSPCertId(cOCSPCertId, obj, cid); - return obj; -} - -/* - * OCSP::Resquest - */ -static VALUE -ossl_ocspreq_alloc(VALUE klass) -{ - OCSP_REQUEST *req; - VALUE obj; - - if (!(req = OCSP_REQUEST_new())) - ossl_raise(eOCSPError, NULL); - WrapOCSPReq(klass, obj, req); - - return obj; -} - -/* - * call-seq: - * OpenSSL::OCSP::Request.new -> request - * OpenSSL::OCSP::Request.new(request_der) -> request - * - * Creates a new OpenSSL::OCSP::Request. The request may be created empty or - * from a +request_der+ string. - */ - -static VALUE -ossl_ocspreq_initialize(int argc, VALUE *argv, VALUE self) -{ - VALUE arg; - const unsigned char *p; - - rb_scan_args(argc, argv, "01", &arg); - if(!NIL_P(arg)){ - OCSP_REQUEST *req = DATA_PTR(self), *x; - arg = ossl_to_der_if_possible(arg); - StringValue(arg); - p = (unsigned char*)RSTRING_PTR(arg); - x = d2i_OCSP_REQUEST(&req, &p, RSTRING_LEN(arg)); - DATA_PTR(self) = req; - if(!x){ - ossl_raise(eOCSPError, "cannot load DER encoded request"); - } - } - - return self; -} - -/* - * call-seq: - * request.add_nonce(nonce = nil) -> request - * - * Adds a +nonce+ to the OCSP request. If no nonce is given a random one will - * be generated. - * - * The nonce is used to prevent replay attacks but some servers do not support - * it. - */ - -static VALUE -ossl_ocspreq_add_nonce(int argc, VALUE *argv, VALUE self) -{ - OCSP_REQUEST *req; - VALUE val; - int ret; - - rb_scan_args(argc, argv, "01", &val); - if(NIL_P(val)) { - GetOCSPReq(self, req); - ret = OCSP_request_add1_nonce(req, NULL, -1); - } - else{ - StringValue(val); - GetOCSPReq(self, req); - ret = OCSP_request_add1_nonce(req, (unsigned char *)RSTRING_PTR(val), RSTRING_LENINT(val)); - } - if(!ret) ossl_raise(eOCSPError, NULL); - - return self; -} - -/* - * call-seq: - * request.check_nonce(response) -> result - * - * Checks the nonce validity for this request and +response+. - * - * The return value is one of the following: - * - * -1 :: nonce in request only. - * 0 :: nonces both present and not equal. - * 1 :: nonces present and equal. - * 2 :: nonces both absent. - * 3 :: nonce present in response only. - * - * For most responses, clients can check +result+ > 0. If a responder doesn't - * handle nonces <code>result.nonzero?</code> may be necessary. A result of - * <code>0</code> is always an error. - */ - -static VALUE -ossl_ocspreq_check_nonce(VALUE self, VALUE basic_resp) -{ - OCSP_REQUEST *req; - OCSP_BASICRESP *bs; - int res; - - GetOCSPReq(self, req); - SafeGetOCSPBasicRes(basic_resp, bs); - res = OCSP_check_nonce(req, bs); - - return INT2NUM(res); -} - -/* - * call-seq: - * request.add_certid(certificate_id) -> request - * - * Adds +certificate_id+ to the request. - */ - -static VALUE -ossl_ocspreq_add_certid(VALUE self, VALUE certid) -{ - OCSP_REQUEST *req; - OCSP_CERTID *id; - - GetOCSPReq(self, req); - GetOCSPCertId(certid, id); - if(!OCSP_request_add0_id(req, OCSP_CERTID_dup(id))) - ossl_raise(eOCSPError, NULL); - - return self; -} - -/* - * call-seq: - * request.certid -> [certificate_id, ...] - * - * Returns all certificate IDs in this request. - */ - -static VALUE -ossl_ocspreq_get_certid(VALUE self) -{ - OCSP_REQUEST *req; - OCSP_ONEREQ *one; - OCSP_CERTID *id; - VALUE ary, tmp; - int i, count; - - GetOCSPReq(self, req); - count = OCSP_request_onereq_count(req); - ary = (count > 0) ? rb_ary_new() : Qnil; - for(i = 0; i < count; i++){ - one = OCSP_request_onereq_get0(req, i); - if(!(id = OCSP_CERTID_dup(OCSP_onereq_get0_id(one)))) - ossl_raise(eOCSPError, NULL); - WrapOCSPCertId(cOCSPCertId, tmp, id); - rb_ary_push(ary, tmp); - } - - return ary; -} - -/* - * call-seq: - * request.sign(signer_cert, signer_key) -> self - * request.sign(signer_cert, signer_key, certificates) -> self - * request.sign(signer_cert, signer_key, certificates, flags) -> self - * - * Signs this OCSP request using +signer_cert+ and +signer_key+. - * +certificates+ is an optional Array of certificates that may be included in - * the request. - */ - -static VALUE -ossl_ocspreq_sign(int argc, VALUE *argv, VALUE self) -{ - VALUE signer_cert, signer_key, certs, flags; - OCSP_REQUEST *req; - X509 *signer; - EVP_PKEY *key; - STACK_OF(X509) *x509s; - unsigned long flg; - int ret; - - rb_scan_args(argc, argv, "22", &signer_cert, &signer_key, &certs, &flags); - signer = GetX509CertPtr(signer_cert); - key = GetPrivPKeyPtr(signer_key); - flg = NIL_P(flags) ? 0 : NUM2INT(flags); - if(NIL_P(certs)){ - x509s = sk_X509_new_null(); - flags |= OCSP_NOCERTS; - } - else x509s = ossl_x509_ary2sk(certs); - GetOCSPReq(self, req); - ret = OCSP_request_sign(req, signer, key, EVP_sha1(), x509s, flg); - sk_X509_pop_free(x509s, X509_free); - if(!ret) ossl_raise(eOCSPError, NULL); - - return self; -} - -/* - * call-seq: - * request.verify(certificates, store) -> true or false - * request.verify(certificates, store, flags) -> true or false - * - * Verifies this request using the given +certificates+ and X509 +store+. - */ - -static VALUE -ossl_ocspreq_verify(int argc, VALUE *argv, VALUE self) -{ - VALUE certs, store, flags; - OCSP_REQUEST *req; - STACK_OF(X509) *x509s; - X509_STORE *x509st; - int flg, result; - - rb_scan_args(argc, argv, "21", &certs, &store, &flags); - x509st = GetX509StorePtr(store); - flg = NIL_P(flags) ? 0 : NUM2INT(flags); - x509s = ossl_x509_ary2sk(certs); - GetOCSPReq(self, req); - result = OCSP_request_verify(req, x509s, x509st, flg); - sk_X509_pop_free(x509s, X509_free); - if(!result) rb_warn("%s", ERR_error_string(ERR_peek_error(), NULL)); - - return result ? Qtrue : Qfalse; -} - -/* - * Returns this request as a DER-encoded string - */ - -static VALUE -ossl_ocspreq_to_der(VALUE self) -{ - OCSP_REQUEST *req; - VALUE str; - unsigned char *p; - long len; - - GetOCSPReq(self, req); - if((len = i2d_OCSP_REQUEST(req, NULL)) <= 0) - ossl_raise(eOCSPError, NULL); - str = rb_str_new(0, len); - p = (unsigned char *)RSTRING_PTR(str); - if(i2d_OCSP_REQUEST(req, &p) <= 0) - ossl_raise(eOCSPError, NULL); - ossl_str_adjust(str, p); - - return str; -} - -/* - * OCSP::Response - */ - -/* call-seq: - * OpenSSL::OCSP::Response.create(status, basic_response = nil) -> response - * - * Creates an OpenSSL::OCSP::Response from +status+ and +basic_response+. - */ - -static VALUE -ossl_ocspres_s_create(VALUE klass, VALUE status, VALUE basic_resp) -{ - OCSP_BASICRESP *bs; - OCSP_RESPONSE *res; - VALUE obj; - int st = NUM2INT(status); - - if(NIL_P(basic_resp)) bs = NULL; - else GetOCSPBasicRes(basic_resp, bs); /* NO NEED TO DUP */ - if(!(res = OCSP_response_create(st, bs))) - ossl_raise(eOCSPError, NULL); - WrapOCSPRes(klass, obj, res); - - return obj; -} - -static VALUE -ossl_ocspres_alloc(VALUE klass) -{ - OCSP_RESPONSE *res; - VALUE obj; - - if(!(res = OCSP_RESPONSE_new())) - ossl_raise(eOCSPError, NULL); - WrapOCSPRes(klass, obj, res); - - return obj; -} - -/* - * call-seq: - * OpenSSL::OCSP::Response.new -> response - * OpenSSL::OCSP::Response.new(response_der) -> response - * - * Creates a new OpenSSL::OCSP::Response. The response may be created empty or - * from a +response_der+ string. - */ - -static VALUE -ossl_ocspres_initialize(int argc, VALUE *argv, VALUE self) -{ - VALUE arg; - const unsigned char *p; - - rb_scan_args(argc, argv, "01", &arg); - if(!NIL_P(arg)){ - OCSP_RESPONSE *res = DATA_PTR(self), *x; - arg = ossl_to_der_if_possible(arg); - StringValue(arg); - p = (unsigned char *)RSTRING_PTR(arg); - x = d2i_OCSP_RESPONSE(&res, &p, RSTRING_LEN(arg)); - DATA_PTR(self) = res; - if(!x){ - ossl_raise(eOCSPError, "cannot load DER encoded response"); - } - } - - return self; -} - -/* - * call-seq: - * response.status -> Integer - * - * Returns the status of the response. - */ - -static VALUE -ossl_ocspres_status(VALUE self) -{ - OCSP_RESPONSE *res; - int st; - - GetOCSPRes(self, res); - st = OCSP_response_status(res); - - return INT2NUM(st); -} - -/* - * call-seq: - * response.status_string -> String - * - * Returns a status string for the response. - */ - -static VALUE -ossl_ocspres_status_string(VALUE self) -{ - OCSP_RESPONSE *res; - int st; - - GetOCSPRes(self, res); - st = OCSP_response_status(res); - - return rb_str_new2(OCSP_response_status_str(st)); -} - -/* - * call-seq: - * response.basic - * - * Returns a BasicResponse for this response - */ - -static VALUE -ossl_ocspres_get_basic(VALUE self) -{ - OCSP_RESPONSE *res; - OCSP_BASICRESP *bs; - VALUE ret; - - GetOCSPRes(self, res); - if(!(bs = OCSP_response_get1_basic(res))) - return Qnil; - WrapOCSPBasicRes(cOCSPBasicRes, ret, bs); - - return ret; -} - -/* - * call-seq: - * response.to_der -> String - * - * Returns this response as a DER-encoded string. - */ - -static VALUE -ossl_ocspres_to_der(VALUE self) -{ - OCSP_RESPONSE *res; - VALUE str; - long len; - unsigned char *p; - - GetOCSPRes(self, res); - if((len = i2d_OCSP_RESPONSE(res, NULL)) <= 0) - ossl_raise(eOCSPError, NULL); - str = rb_str_new(0, len); - p = (unsigned char *)RSTRING_PTR(str); - if(i2d_OCSP_RESPONSE(res, &p) <= 0) - ossl_raise(eOCSPError, NULL); - ossl_str_adjust(str, p); - - return str; -} - -/* - * OCSP::BasicResponse - */ -static VALUE -ossl_ocspbres_alloc(VALUE klass) -{ - OCSP_BASICRESP *bs; - VALUE obj; - - if(!(bs = OCSP_BASICRESP_new())) - ossl_raise(eOCSPError, NULL); - WrapOCSPBasicRes(klass, obj, bs); - - return obj; -} - -/* - * call-seq: - * OpenSSL::OCSP::BasicResponse.new(*) -> basic_response - * - * Creates a new BasicResponse and ignores all arguments. - */ - -static VALUE -ossl_ocspbres_initialize(int argc, VALUE *argv, VALUE self) -{ - return self; -} - -/* - * call-seq: - * basic_response.copy_nonce(request) -> Integer - * - * Copies the nonce from +request+ into this response. Returns 1 on success - * and 0 on failure. - */ - -static VALUE -ossl_ocspbres_copy_nonce(VALUE self, VALUE request) -{ - OCSP_BASICRESP *bs; - OCSP_REQUEST *req; - int ret; - - GetOCSPBasicRes(self, bs); - SafeGetOCSPReq(request, req); - ret = OCSP_copy_nonce(bs, req); - - return INT2NUM(ret); -} - -/* - * call-seq: - * basic_response.add_nonce(nonce = nil) - * - * Adds +nonce+ to this response. If no nonce was provided a random nonce - * will be added. - */ - -static VALUE -ossl_ocspbres_add_nonce(int argc, VALUE *argv, VALUE self) -{ - OCSP_BASICRESP *bs; - VALUE val; - int ret; - - rb_scan_args(argc, argv, "01", &val); - if(NIL_P(val)) { - GetOCSPBasicRes(self, bs); - ret = OCSP_basic_add1_nonce(bs, NULL, -1); - } - else{ - StringValue(val); - GetOCSPBasicRes(self, bs); - ret = OCSP_basic_add1_nonce(bs, (unsigned char *)RSTRING_PTR(val), RSTRING_LENINT(val)); - } - if(!ret) ossl_raise(eOCSPError, NULL); - - return self; -} - -/* - * call-seq: - * basic_response.add_status(certificate_id, status, reason, revocation_time, this_update, next_update, extensions) -> basic_response - * - * Adds a validation +status+ (0 for revoked, 1 for success) to this - * response for +certificate_id+. +reason+ describes the reason for the - * revocation, if any. - * - * The +revocation_time+, +this_update+ and +next_update+ are times for the - * certificate's revocation time, the time of this status and the next update - * time for a new status, respectively. - * - * +extensions+ may be an Array of OpenSSL::X509::Extension that will - * be added to this response or nil. - */ - -static VALUE -ossl_ocspbres_add_status(VALUE self, VALUE cid, VALUE status, - VALUE reason, VALUE revtime, - VALUE thisupd, VALUE nextupd, VALUE ext) -{ - OCSP_BASICRESP *bs; - OCSP_SINGLERESP *single; - OCSP_CERTID *id; - int st, rsn; - ASN1_TIME *ths, *nxt, *rev; - int error, i, rstatus = 0; - VALUE tmp; - - st = NUM2INT(status); - rsn = NIL_P(status) ? 0 : NUM2INT(reason); - if(!NIL_P(ext)){ - /* All ary's members should be X509Extension */ - Check_Type(ext, T_ARRAY); - for (i = 0; i < RARRAY_LEN(ext); i++) - OSSL_Check_Kind(RARRAY_PTR(ext)[i], cX509Ext); - } - - error = 0; - ths = nxt = rev = NULL; - if(!NIL_P(revtime)){ - tmp = rb_protect(rb_Integer, revtime, &rstatus); - if(rstatus) goto err; - rev = X509_gmtime_adj(NULL, NUM2INT(tmp)); - } - tmp = rb_protect(rb_Integer, thisupd, &rstatus); - if(rstatus) goto err; - ths = X509_gmtime_adj(NULL, NUM2INT(tmp)); - tmp = rb_protect(rb_Integer, nextupd, &rstatus); - if(rstatus) goto err; - nxt = X509_gmtime_adj(NULL, NUM2INT(tmp)); - - GetOCSPBasicRes(self, bs); - SafeGetOCSPCertId(cid, id); - if(!(single = OCSP_basic_add1_status(bs, id, st, rsn, rev, ths, nxt))){ - error = 1; - goto err; - } - - if(!NIL_P(ext)){ - X509_EXTENSION *x509ext; - sk_X509_EXTENSION_pop_free(single->singleExtensions, X509_EXTENSION_free); - single->singleExtensions = NULL; - for(i = 0; i < RARRAY_LEN(ext); i++){ - x509ext = DupX509ExtPtr(RARRAY_PTR(ext)[i]); - if(!OCSP_SINGLERESP_add_ext(single, x509ext, -1)){ - X509_EXTENSION_free(x509ext); - error = 1; - goto err; - } - X509_EXTENSION_free(x509ext); - } - } - - err: - ASN1_TIME_free(ths); - ASN1_TIME_free(nxt); - ASN1_TIME_free(rev); - if(error) ossl_raise(eOCSPError, NULL); - if(rstatus) rb_jump_tag(rstatus); - - return self; -} - -/* - * call-seq: - * basic_response.status -> statuses - * - * Returns an Array of statuses for this response. Each status contains a - * CertificateId, the status (0 for success, 1 for revoked), the reason for - * the status, the revocation time, the time of this update, the time for the - * next update and a list of OpenSSL::X509::Extensions. - */ - -static VALUE -ossl_ocspbres_get_status(VALUE self) -{ - OCSP_BASICRESP *bs; - OCSP_SINGLERESP *single; - OCSP_CERTID *cid; - ASN1_TIME *revtime, *thisupd, *nextupd; - int status, reason; - X509_EXTENSION *x509ext; - VALUE ret, ary, ext; - int count, ext_count, i, j; - - GetOCSPBasicRes(self, bs); - ret = rb_ary_new(); - count = OCSP_resp_count(bs); - for(i = 0; i < count; i++){ - single = OCSP_resp_get0(bs, i); - if(!single) continue; - - revtime = thisupd = nextupd = NULL; - status = OCSP_single_get0_status(single, &reason, &revtime, - &thisupd, &nextupd); - if(status < 0) continue; - if(!(cid = OCSP_CERTID_dup(single->certId))) - ossl_raise(eOCSPError, NULL); - ary = rb_ary_new(); - rb_ary_push(ary, ossl_ocspcertid_new(cid)); - rb_ary_push(ary, INT2NUM(status)); - rb_ary_push(ary, INT2NUM(reason)); - rb_ary_push(ary, revtime ? asn1time_to_time(revtime) : Qnil); - rb_ary_push(ary, thisupd ? asn1time_to_time(thisupd) : Qnil); - rb_ary_push(ary, nextupd ? asn1time_to_time(nextupd) : Qnil); - ext = rb_ary_new(); - ext_count = OCSP_SINGLERESP_get_ext_count(single); - for(j = 0; j < ext_count; j++){ - x509ext = OCSP_SINGLERESP_get_ext(single, j); - rb_ary_push(ext, ossl_x509ext_new(x509ext)); - } - rb_ary_push(ary, ext); - rb_ary_push(ret, ary); - } - - return ret; -} - -/* - * call-seq: - * basic_response.sign(signer_cert, signer_key) -> self - * basic_response.sign(signer_cert, signer_key, certificates) -> self - * basic_response.sign(signer_cert, signer_key, certificates, flags) -> self - * - * Signs this response using the +signer_cert+ and +signer_key+. Additional - * +certificates+ may be added to the signature along with a set of +flags+. - */ - -static VALUE -ossl_ocspbres_sign(int argc, VALUE *argv, VALUE self) -{ - VALUE signer_cert, signer_key, certs, flags; - OCSP_BASICRESP *bs; - X509 *signer; - EVP_PKEY *key; - STACK_OF(X509) *x509s; - unsigned long flg; - int ret; - - rb_scan_args(argc, argv, "22", &signer_cert, &signer_key, &certs, &flags); - signer = GetX509CertPtr(signer_cert); - key = GetPrivPKeyPtr(signer_key); - flg = NIL_P(flags) ? 0 : NUM2INT(flags); - if(NIL_P(certs)){ - x509s = sk_X509_new_null(); - flg |= OCSP_NOCERTS; - } - else{ - x509s = ossl_x509_ary2sk(certs); - } - GetOCSPBasicRes(self, bs); - ret = OCSP_basic_sign(bs, signer, key, EVP_sha1(), x509s, flg); - sk_X509_pop_free(x509s, X509_free); - if(!ret) ossl_raise(eOCSPError, NULL); - - return self; -} - -/* - * call-seq: - * basic_response.verify(certificates, store) -> true or false - * basic_response.verify(certificates, store, flags) -> true or false - * - * Verifies the signature of the response using the given +certificates+, - * +store+ and +flags+. - */ -static VALUE -ossl_ocspbres_verify(int argc, VALUE *argv, VALUE self) -{ - VALUE certs, store, flags, result; - OCSP_BASICRESP *bs; - STACK_OF(X509) *x509s; - X509_STORE *x509st; - int flg; - - rb_scan_args(argc, argv, "21", &certs, &store, &flags); - x509st = GetX509StorePtr(store); - flg = NIL_P(flags) ? 0 : NUM2INT(flags); - x509s = ossl_x509_ary2sk(certs); - GetOCSPBasicRes(self, bs); - result = OCSP_basic_verify(bs, x509s, x509st, flg) > 0 ? Qtrue : Qfalse; - sk_X509_pop_free(x509s, X509_free); - if(!result) rb_warn("%s", ERR_error_string(ERR_peek_error(), NULL)); - - return result; -} - -/* - * OCSP::CertificateId - */ -static VALUE -ossl_ocspcid_alloc(VALUE klass) -{ - OCSP_CERTID *id; - VALUE obj; - - if(!(id = OCSP_CERTID_new())) - ossl_raise(eOCSPError, NULL); - WrapOCSPCertId(klass, obj, id); - - return obj; -} - -/* - * call-seq: - * OpenSSL::OCSP::CertificateId.new(subject, issuer, digest = nil) -> certificate_id - * - * Creates a new OpenSSL::OCSP::CertificateId for the given +subject+ and - * +issuer+ X509 certificates. The +digest+ is used to compute the - * certificate ID and must be an OpenSSL::Digest instance. - */ - -static VALUE -ossl_ocspcid_initialize(int argc, VALUE *argv, VALUE self) -{ - OCSP_CERTID *id, *newid; - X509 *x509s, *x509i; - VALUE subject, issuer, digest; - const EVP_MD *md; - - if (rb_scan_args(argc, argv, "21", &subject, &issuer, &digest) == 0) { - return self; - } - - x509s = GetX509CertPtr(subject); /* NO NEED TO DUP */ - x509i = GetX509CertPtr(issuer); /* NO NEED TO DUP */ - - if (!NIL_P(digest)) { - md = GetDigestPtr(digest); - newid = OCSP_cert_to_id(md, x509s, x509i); - } else { - newid = OCSP_cert_to_id(NULL, x509s, x509i); - } - if(!newid) - ossl_raise(eOCSPError, NULL); - GetOCSPCertId(self, id); - OCSP_CERTID_free(id); - RDATA(self)->data = newid; - - return self; -} - -/* - * call-seq: - * certificate_id.cmp(other) -> true or false - * - * Compares this certificate id with +other+ and returns true if they are the - * same. - */ -static VALUE -ossl_ocspcid_cmp(VALUE self, VALUE other) -{ - OCSP_CERTID *id, *id2; - int result; - - GetOCSPCertId(self, id); - SafeGetOCSPCertId(other, id2); - result = OCSP_id_cmp(id, id2); - - return (result == 0) ? Qtrue : Qfalse; -} - -/* - * call-seq: - * certificate_id.cmp_issuer(other) -> true or false - * - * Compares this certificate id's issuer with +other+ and returns true if - * they are the same. - */ - -static VALUE -ossl_ocspcid_cmp_issuer(VALUE self, VALUE other) -{ - OCSP_CERTID *id, *id2; - int result; - - GetOCSPCertId(self, id); - SafeGetOCSPCertId(other, id2); - result = OCSP_id_issuer_cmp(id, id2); - - return (result == 0) ? Qtrue : Qfalse; -} - -/* - * call-seq: - * certificate_id.get_serial -> Integer - * - * Returns the serial number of the issuing certificate. - */ - -static VALUE -ossl_ocspcid_get_serial(VALUE self) -{ - OCSP_CERTID *id; - - GetOCSPCertId(self, id); - - return asn1integer_to_num(id->serialNumber); -} - -void -Init_ossl_ocsp(void) -{ - /* - * OpenSSL::OCSP implements Online Certificate Status Protocol requests - * and responses. - * - * Creating and sending an OCSP request requires a subject certificate - * that contains an OCSP URL in an authorityInfoAccess extension and the - * issuer certificate for the subject certificate. First, load the issuer - * and subject certificates: - * - * subject = OpenSSL::X509::Certificate.new subject_pem - * issuer = OpenSSL::X509::Certificate.new issuer_pem - * - * To create the request we need to create a certificate ID for the - * subject certificate so the CA knows which certificate we are asking - * about: - * - * digest = OpenSSL::Digest::SHA1.new - * certificate_id = - * OpenSSL::OCSP::CertificateId.new subject, issuer, digest - * - * Then create a request and add the certificate ID to it: - * - * request = OpenSSL::OCSP::Request.new - * request.add_certid certificate_id - * - * Adding a nonce to the request protects against replay attacks but not - * all CA process the nonce. - * - * request.add_nonce - * - * To submit the request to the CA for verification we need to extract the - * OCSP URI from the subject certificate: - * - * authority_info_access = subject.extensions.find do |extension| - * extension.oid == 'authorityInfoAccess' - * end - * - * descriptions = authority_info_access.value.split "\n" - * ocsp = descriptions.find do |description| - * description.start_with? 'OCSP' - * end - * - * require 'uri' - * - * ocsp_uri = URI ocsp[/URI:(.*)/, 1] - * - * To submit the request we'll POST the request to the OCSP URI (per RFC - * 2560). Note that we only handle HTTP requests and don't handle any - * redirects in this example, so this is insufficient for serious use. - * - * require 'net/http' - * - * http_response = - * Net::HTTP.start ocsp_uri.hostname, ocsp.port do |http| - * http.post ocsp_uri.path, request.to_der, - * 'content-type' => 'application/ocsp-request' - * end - * - * response = OpenSSL::OCSP::Response.new http_response.body - * response_basic = response.basic - * - * First we check if the response has a valid signature. Without a valid - * signature we cannot trust it. If you get a failure here you may be - * missing a system certificate store or may be missing the intermediate - * certificates. - * - * store = OpenSSL::X509::Store.new - * store.set_default_paths - * - * unless response.verify [], store then - * raise 'response is not signed by a trusted certificate' - * end - * - * The response contains the status information (success/fail). We can - * display the status as a string: - * - * puts response.status_string #=> successful - * - * Next we need to know the response details to determine if the response - * matches our request. First we check the nonce. Again, not all CAs - * support a nonce. See Request#check_nonce for the meanings of the - * return values. - * - * p request.check_nonce basic_response #=> value from -1 to 3 - * - * Then extract the status information from the basic response. (You can - * check multiple certificates in a request, but for this example we only - * submitted one.) - * - * response_certificate_id, status, reason, revocation_time, - * this_update, next_update, extensions = basic_response.status - * - * Then check the various fields. - * - * unless response_certificate_id == certificate_id then - * raise 'certificate id mismatch' - * end - * - * now = Time.now - * - * if this_update > now then - * raise 'update date is in the future' - * end - * - * if now > next_update then - * raise 'next update time has passed' - * end - */ - - mOCSP = rb_define_module_under(mOSSL, "OCSP"); - - /* - * OCSP error class. - */ - - eOCSPError = rb_define_class_under(mOCSP, "OCSPError", eOSSLError); - - /* - * An OpenSSL::OCSP::Request contains the certificate information for - * determining if a certificate has been revoked or not. A Request can be - * created for a certificate or from a DER-encoded request created - * elsewhere. - */ - - cOCSPReq = rb_define_class_under(mOCSP, "Request", rb_cObject); - rb_define_alloc_func(cOCSPReq, ossl_ocspreq_alloc); - rb_define_method(cOCSPReq, "initialize", ossl_ocspreq_initialize, -1); - rb_define_method(cOCSPReq, "add_nonce", ossl_ocspreq_add_nonce, -1); - rb_define_method(cOCSPReq, "check_nonce", ossl_ocspreq_check_nonce, 1); - rb_define_method(cOCSPReq, "add_certid", ossl_ocspreq_add_certid, 1); - rb_define_method(cOCSPReq, "certid", ossl_ocspreq_get_certid, 0); - rb_define_method(cOCSPReq, "sign", ossl_ocspreq_sign, -1); - rb_define_method(cOCSPReq, "verify", ossl_ocspreq_verify, -1); - rb_define_method(cOCSPReq, "to_der", ossl_ocspreq_to_der, 0); - - /* - * An OpenSSL::OCSP::Response contains the status of a certificate check - * which is created from an OpenSSL::OCSP::Request. - */ - - cOCSPRes = rb_define_class_under(mOCSP, "Response", rb_cObject); - rb_define_singleton_method(cOCSPRes, "create", ossl_ocspres_s_create, 2); - rb_define_alloc_func(cOCSPRes, ossl_ocspres_alloc); - rb_define_method(cOCSPRes, "initialize", ossl_ocspres_initialize, -1); - rb_define_method(cOCSPRes, "status", ossl_ocspres_status, 0); - rb_define_method(cOCSPRes, "status_string", ossl_ocspres_status_string, 0); - rb_define_method(cOCSPRes, "basic", ossl_ocspres_get_basic, 0); - rb_define_method(cOCSPRes, "to_der", ossl_ocspres_to_der, 0); - - /* - * An OpenSSL::OCSP::BasicResponse contains the status of a certificate - * check which is created from an OpenSSL::OCSP::Request. A - * BasicResponse is more detailed than a Response. - */ - - cOCSPBasicRes = rb_define_class_under(mOCSP, "BasicResponse", rb_cObject); - rb_define_alloc_func(cOCSPBasicRes, ossl_ocspbres_alloc); - rb_define_method(cOCSPBasicRes, "initialize", ossl_ocspbres_initialize, -1); - rb_define_method(cOCSPBasicRes, "copy_nonce", ossl_ocspbres_copy_nonce, 1); - rb_define_method(cOCSPBasicRes, "add_nonce", ossl_ocspbres_add_nonce, -1); - rb_define_method(cOCSPBasicRes, "add_status", ossl_ocspbres_add_status, 7); - rb_define_method(cOCSPBasicRes, "status", ossl_ocspbres_get_status, 0); - rb_define_method(cOCSPBasicRes, "sign", ossl_ocspbres_sign, -1); - rb_define_method(cOCSPBasicRes, "verify", ossl_ocspbres_verify, -1); - - /* - * An OpenSSL::OCSP::CertificateId identifies a certificate to the CA so - * that a status check can be performed. - */ - - cOCSPCertId = rb_define_class_under(mOCSP, "CertificateId", rb_cObject); - rb_define_alloc_func(cOCSPCertId, ossl_ocspcid_alloc); - rb_define_method(cOCSPCertId, "initialize", ossl_ocspcid_initialize, -1); - rb_define_method(cOCSPCertId, "cmp", ossl_ocspcid_cmp, 1); - rb_define_method(cOCSPCertId, "cmp_issuer", ossl_ocspcid_cmp_issuer, 1); - rb_define_method(cOCSPCertId, "serial", ossl_ocspcid_get_serial, 0); - - /* Internal error in issuer */ - rb_define_const(mOCSP, "RESPONSE_STATUS_INTERNALERROR", INT2NUM(OCSP_RESPONSE_STATUS_INTERNALERROR)); - - /* Illegal confirmation request */ - rb_define_const(mOCSP, "RESPONSE_STATUS_MALFORMEDREQUEST", INT2NUM(OCSP_RESPONSE_STATUS_MALFORMEDREQUEST)); - - /* The certificate was revoked for an unknown reason */ - rb_define_const(mOCSP, "REVOKED_STATUS_NOSTATUS", INT2NUM(OCSP_REVOKED_STATUS_NOSTATUS)); - - /* You must sign the request and resubmit */ - rb_define_const(mOCSP, "RESPONSE_STATUS_SIGREQUIRED", INT2NUM(OCSP_RESPONSE_STATUS_SIGREQUIRED)); - - /* Response has valid confirmations */ - rb_define_const(mOCSP, "RESPONSE_STATUS_SUCCESSFUL", INT2NUM(OCSP_RESPONSE_STATUS_SUCCESSFUL)); - - /* Try again later */ - rb_define_const(mOCSP, "RESPONSE_STATUS_TRYLATER", INT2NUM(OCSP_RESPONSE_STATUS_TRYLATER)); - - /* The certificate subject's name or other information changed */ - rb_define_const(mOCSP, "REVOKED_STATUS_AFFILIATIONCHANGED", INT2NUM(OCSP_REVOKED_STATUS_AFFILIATIONCHANGED)); - - /* This CA certificate was revoked due to a key compromise */ - rb_define_const(mOCSP, "REVOKED_STATUS_CACOMPROMISE", INT2NUM(OCSP_REVOKED_STATUS_CACOMPROMISE)); - - /* The certificate is on hold */ - rb_define_const(mOCSP, "REVOKED_STATUS_CERTIFICATEHOLD", INT2NUM(OCSP_REVOKED_STATUS_CERTIFICATEHOLD)); - - /* The certificate is no longer needed */ - rb_define_const(mOCSP, "REVOKED_STATUS_CESSATIONOFOPERATION", INT2NUM(OCSP_REVOKED_STATUS_CESSATIONOFOPERATION)); - - /* The certificate was revoked due to a key compromise */ - rb_define_const(mOCSP, "REVOKED_STATUS_KEYCOMPROMISE", INT2NUM(OCSP_REVOKED_STATUS_KEYCOMPROMISE)); - - /* The certificate was previously on hold and should now be removed from - * the CRL */ - rb_define_const(mOCSP, "REVOKED_STATUS_REMOVEFROMCRL", INT2NUM(OCSP_REVOKED_STATUS_REMOVEFROMCRL)); - - /* The certificate was superseded by a new certificate */ - rb_define_const(mOCSP, "REVOKED_STATUS_SUPERSEDED", INT2NUM(OCSP_REVOKED_STATUS_SUPERSEDED)); - - /* Your request is unauthorized. */ - rb_define_const(mOCSP, "RESPONSE_STATUS_UNAUTHORIZED", INT2NUM(OCSP_RESPONSE_STATUS_UNAUTHORIZED)); - - /* The certificate was revoked for an unspecified reason */ - rb_define_const(mOCSP, "REVOKED_STATUS_UNSPECIFIED", INT2NUM(OCSP_REVOKED_STATUS_UNSPECIFIED)); - - /* Do not include certificates in the response */ - rb_define_const(mOCSP, "NOCERTS", INT2NUM(OCSP_NOCERTS)); - - /* Do not search certificates contained in the response for a signer */ - rb_define_const(mOCSP, "NOINTERN", INT2NUM(OCSP_NOINTERN)); - - /* Do not check the signature on the response */ - rb_define_const(mOCSP, "NOSIGS", INT2NUM(OCSP_NOSIGS)); - - /* Do not verify the certificate chain on the response */ - rb_define_const(mOCSP, "NOCHAIN", INT2NUM(OCSP_NOCHAIN)); - - /* Do not verify the response at all */ - rb_define_const(mOCSP, "NOVERIFY", INT2NUM(OCSP_NOVERIFY)); - - /* Do not check trust */ - rb_define_const(mOCSP, "NOEXPLICIT", INT2NUM(OCSP_NOEXPLICIT)); - - /* (This flag is not used by OpenSSL 1.0.1g) */ - rb_define_const(mOCSP, "NOCASIGN", INT2NUM(OCSP_NOCASIGN)); - - /* (This flag is not used by OpenSSL 1.0.1g) */ - rb_define_const(mOCSP, "NODELEGATED", INT2NUM(OCSP_NODELEGATED)); - - /* Do not make additional signing certificate checks */ - rb_define_const(mOCSP, "NOCHECKS", INT2NUM(OCSP_NOCHECKS)); - - /* Do not verify additional certificates */ - rb_define_const(mOCSP, "TRUSTOTHER", INT2NUM(OCSP_TRUSTOTHER)); - - /* Identify the response by signing the certificate key ID */ - rb_define_const(mOCSP, "RESPID_KEY", INT2NUM(OCSP_RESPID_KEY)); - - /* Do not include producedAt time in response */ - rb_define_const(mOCSP, "NOTIME", INT2NUM(OCSP_NOTIME)); - - /* Indicates the certificate is not revoked but does not necessarily mean - * the certificate was issued or that this response is within the - * certificate's validity interval */ - rb_define_const(mOCSP, "V_CERTSTATUS_GOOD", INT2NUM(V_OCSP_CERTSTATUS_GOOD)); - /* Indicates the certificate has been revoked either permanently or - * temporarily (on hold). */ - rb_define_const(mOCSP, "V_CERTSTATUS_REVOKED", INT2NUM(V_OCSP_CERTSTATUS_REVOKED)); - - /* Indicates the responder does not know about the certificate being - * requested. */ - rb_define_const(mOCSP, "V_CERTSTATUS_UNKNOWN", INT2NUM(V_OCSP_CERTSTATUS_UNKNOWN)); - - /* The responder ID is based on the key name. */ - rb_define_const(mOCSP, "V_RESPID_NAME", INT2NUM(V_OCSP_RESPID_NAME)); - - /* The responder ID is based on the public key. */ - rb_define_const(mOCSP, "V_RESPID_KEY", INT2NUM(V_OCSP_RESPID_KEY)); -} - -#else /* ! OSSL_OCSP_ENABLED */ -void -Init_ossl_ocsp(void) -{ -} -#endif |