From 830c3a1409cc50c32369d53e5a1992592b443394 Mon Sep 17 00:00:00 2001 From: rhe Date: Sun, 19 Jun 2016 09:42:30 +0000 Subject: openssl: allow passing absolute times in OCSP::BasicResponse#add_status * ext/openssl/ossl_ocsp.c (ossl_ocspbres_add_status): Allow specifying the times (thisUpdate, nextUpdate and revocationTime) with Time objects. Currently they accepts only relative seconds from the current time. This is inconvenience, especially for revocationTime. When Integer is passed, they are still treated as relative times. Since the type check is currently done with rb_Integer(), this is a slightly incompatible change. Hope no one passes a relative time as String or Time object... Also, allow passing nil as nextUpdate. It is optional. * ext/openssl/ruby_missing.h: Define RB_INTEGER_TYPE_P() if not defined. openssl gem will be released before Ruby 2.4.0. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55456 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ext/openssl/ossl_ocsp.c | 89 ++++++++++++++++++++++++++++++---------------- ext/openssl/ruby_missing.h | 5 +++ 2 files changed, 63 insertions(+), 31 deletions(-) (limited to 'ext') diff --git a/ext/openssl/ossl_ocsp.c b/ext/openssl/ossl_ocsp.c index 39f1eb043e..8abe7c268c 100644 --- a/ext/openssl/ossl_ocsp.c +++ b/ext/openssl/ossl_ocsp.c @@ -726,22 +726,49 @@ ossl_ocspbres_add_nonce(int argc, VALUE *argv, VALUE self) return self; } +static VALUE +add_status_convert_time(VALUE obj) +{ + ASN1_TIME *time; + + if (RB_INTEGER_TYPE_P(obj)) + time = X509_gmtime_adj(NULL, NUM2INT(obj)); + else + time = ossl_x509_time_adjust(NULL, obj); + + if (!time) + ossl_raise(eOCSPError, NULL); + + return (VALUE)time; +} + /* * 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 good, 1 for revoked, 2 for unknown) to this - * response for +certificate_id+. +reason+ describes the reason for the - * revocation, if any. + * Adds a certificate status for +certificate_id+. +status+ is the status, and + * must be one of these: + * + * - OpenSSL::OCSP::V_CERTSTATUS_GOOD + * - OpenSSL::OCSP::V_CERTSTATUS_REVOKED + * - OpenSSL::OCSP::V_CERTSTATUS_UNKNOWN + * + * +reason+ and +revocation_time+ can be given only when +status+ is + * OpenSSL::OCSP::V_CERTSTATUS_REVOKED. +reason+ describes the reason for the + * revocation, and must be one of OpenSSL::OCSP::REVOKED_STATUS_* constants. + * +revocation_time+ is the time when the certificate is revoked. + * + * +this_update+ and +next_update+ indicate the time at which ths status is + * verified to be correct and the time at or before which newer information + * will be available, respectively. +next_update+ is optional. * - * 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+ is an Array of OpenSSL::X509::Extension to be included in the + * SingleResponse. This is also optional. * - * +extensions+ may be an Array of OpenSSL::X509::Extension that will - * be added to this response or nil. + * Note that the times, +revocation_time+, +this_update+ and +next_update+ + * can be specified in either of Integer or Time object. If they are Integer, it + * is treated as the relative seconds from the current time. */ - static VALUE ossl_ocspbres_add_status(VALUE self, VALUE cid, VALUE status, VALUE reason, VALUE revtime, @@ -750,36 +777,37 @@ ossl_ocspbres_add_status(VALUE self, VALUE cid, VALUE status, OCSP_BASICRESP *bs; OCSP_SINGLERESP *single; OCSP_CERTID *id; - ASN1_TIME *ths, *nxt, *rev; - int st, rsn, error, rstatus = 0; + ASN1_TIME *ths = NULL, *nxt = NULL, *rev = NULL; + int st, rsn = 0, error = 0, rstatus = 0; long i; VALUE tmp; + GetOCSPBasicRes(self, bs); + SafeGetOCSPCertId(cid, id); 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); + if (!NIL_P(ext)) { /* All ext's members must be X509::Extension */ + ext = rb_check_array_type(ext); for (i = 0; i < RARRAY_LEN(ext); i++) OSSL_Check_Kind(RARRAY_AREF(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)); + if (st == V_OCSP_CERTSTATUS_REVOKED) { + rsn = NUM2INT(reason); + tmp = rb_protect(add_status_convert_time, revtime, &rstatus); + if (rstatus) goto err; + rev = (ASN1_TIME *)tmp; + } + + tmp = rb_protect(add_status_convert_time, thisupd, &rstatus); + if (rstatus) goto err; + ths = (ASN1_TIME *)tmp; + + if (!NIL_P(nextupd)) { + tmp = rb_protect(add_status_convert_time, nextupd, &rstatus); + if (rstatus) goto err; + nxt = (ASN1_TIME *)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; @@ -787,8 +815,7 @@ ossl_ocspbres_add_status(VALUE self, VALUE cid, VALUE status, if(!NIL_P(ext)){ X509_EXTENSION *x509ext; - while ((x509ext = OCSP_SINGLERESP_delete_ext(single, 0))) - X509_EXTENSION_free(x509ext); + for(i = 0; i < RARRAY_LEN(ext); i++){ x509ext = DupX509ExtPtr(RARRAY_AREF(ext, i)); if(!OCSP_SINGLERESP_add_ext(single, x509ext, -1)){ diff --git a/ext/openssl/ruby_missing.h b/ext/openssl/ruby_missing.h index d7384ec32c..f076b1757d 100644 --- a/ext/openssl/ruby_missing.h +++ b/ext/openssl/ruby_missing.h @@ -24,4 +24,9 @@ #define rb_io_t OpenFile #endif +#ifndef RB_INTEGER_TYPE_P +/* for Ruby 2.3 compatibility */ +#define RB_INTEGER_TYPE_P(obj) (RB_FIXNUM_P(obj) || RB_TYPE_P(obj, T_BIGNUM)) +#endif + #endif /* _OSSL_RUBY_MISSING_H_ */ -- cgit v1.2.3