Ruby 1.9.3p327(2012-11-10revision37606)
ext/openssl/ossl_x509crl.c
Go to the documentation of this file.
00001 /*
00002  * $Id: ossl_x509crl.c 32199 2011-06-22 08:41:08Z emboss $
00003  * 'OpenSSL for Ruby' project
00004  * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
00005  * All rights reserved.
00006  */
00007 /*
00008  * This program is licenced under the same licence as Ruby.
00009  * (See the file 'LICENCE'.)
00010  */
00011 #include "ossl.h"
00012 
00013 #define WrapX509CRL(klass, obj, crl) do { \
00014     if (!(crl)) { \
00015         ossl_raise(rb_eRuntimeError, "CRL wasn't initialized!"); \
00016     } \
00017     (obj) = Data_Wrap_Struct((klass), 0, X509_CRL_free, (crl)); \
00018 } while (0)
00019 #define GetX509CRL(obj, crl) do { \
00020     Data_Get_Struct((obj), X509_CRL, (crl)); \
00021     if (!(crl)) { \
00022         ossl_raise(rb_eRuntimeError, "CRL wasn't initialized!"); \
00023     } \
00024 } while (0)
00025 #define SafeGetX509CRL(obj, crl) do { \
00026     OSSL_Check_Kind((obj), cX509CRL); \
00027     GetX509CRL((obj), (crl)); \
00028 } while (0)
00029 
00030 /*
00031  * Classes
00032  */
00033 VALUE cX509CRL;
00034 VALUE eX509CRLError;
00035 
00036 /*
00037  * PUBLIC
00038  */
00039 X509_CRL *
00040 GetX509CRLPtr(VALUE obj)
00041 {
00042     X509_CRL *crl;
00043 
00044     SafeGetX509CRL(obj, crl);
00045 
00046     return crl;
00047 }
00048 
00049 X509_CRL *
00050 DupX509CRLPtr(VALUE obj)
00051 {
00052     X509_CRL *crl;
00053 
00054     SafeGetX509CRL(obj, crl);
00055     CRYPTO_add(&crl->references, 1, CRYPTO_LOCK_X509_CRL);
00056 
00057     return crl;
00058 }
00059 
00060 VALUE
00061 ossl_x509crl_new(X509_CRL *crl)
00062 {
00063     X509_CRL *tmp;
00064     VALUE obj;
00065 
00066     tmp = crl ? X509_CRL_dup(crl) : X509_CRL_new();
00067     if(!tmp) ossl_raise(eX509CRLError, NULL);
00068     WrapX509CRL(cX509CRL, obj, tmp);
00069 
00070     return obj;
00071 }
00072 
00073 /*
00074  * PRIVATE
00075  */
00076 static VALUE
00077 ossl_x509crl_alloc(VALUE klass)
00078 {
00079     X509_CRL *crl;
00080     VALUE obj;
00081 
00082     if (!(crl = X509_CRL_new())) {
00083         ossl_raise(eX509CRLError, NULL);
00084     }
00085     WrapX509CRL(klass, obj, crl);
00086 
00087     return obj;
00088 }
00089 
00090 static VALUE
00091 ossl_x509crl_initialize(int argc, VALUE *argv, VALUE self)
00092 {
00093     BIO *in;
00094     X509_CRL *crl, *x = DATA_PTR(self);
00095     VALUE arg;
00096 
00097     if (rb_scan_args(argc, argv, "01", &arg) == 0) {
00098         return self;
00099     }
00100     arg = ossl_to_der_if_possible(arg);
00101     in = ossl_obj2bio(arg);
00102     crl = PEM_read_bio_X509_CRL(in, &x, NULL, NULL);
00103     DATA_PTR(self) = x;
00104     if (!crl) {
00105         OSSL_BIO_reset(in);
00106         crl = d2i_X509_CRL_bio(in, &x);
00107         DATA_PTR(self) = x;
00108     }
00109     BIO_free(in);
00110     if (!crl) ossl_raise(eX509CRLError, NULL);
00111 
00112     return self;
00113 }
00114 
00115 static VALUE
00116 ossl_x509crl_copy(VALUE self, VALUE other)
00117 {
00118     X509_CRL *a, *b, *crl;
00119 
00120     rb_check_frozen(self);
00121     if (self == other) return self;
00122     GetX509CRL(self, a);
00123     SafeGetX509CRL(other, b);
00124     if (!(crl = X509_CRL_dup(b))) {
00125         ossl_raise(eX509CRLError, NULL);
00126     }
00127     X509_CRL_free(a);
00128     DATA_PTR(self) = crl;
00129 
00130     return self;
00131 }
00132 
00133 static VALUE
00134 ossl_x509crl_get_version(VALUE self)
00135 {
00136     X509_CRL *crl;
00137     long ver;
00138 
00139     GetX509CRL(self, crl);
00140     ver = X509_CRL_get_version(crl);
00141 
00142     return LONG2NUM(ver);
00143 }
00144 
00145 static VALUE
00146 ossl_x509crl_set_version(VALUE self, VALUE version)
00147 {
00148     X509_CRL *crl;
00149     long ver;
00150 
00151     if ((ver = NUM2LONG(version)) < 0) {
00152         ossl_raise(eX509CRLError, "version must be >= 0!");
00153     }
00154     GetX509CRL(self, crl);
00155     if (!X509_CRL_set_version(crl, ver)) {
00156         ossl_raise(eX509CRLError, NULL);
00157     }
00158 
00159     return version;
00160 }
00161 
00162 static VALUE
00163 ossl_x509crl_get_signature_algorithm(VALUE self)
00164 {
00165     X509_CRL *crl;
00166     BIO *out;
00167     BUF_MEM *buf;
00168     VALUE str;
00169 
00170     GetX509CRL(self, crl);
00171     if (!(out = BIO_new(BIO_s_mem()))) {
00172         ossl_raise(eX509CRLError, NULL);
00173     }
00174     if (!i2a_ASN1_OBJECT(out, crl->sig_alg->algorithm)) {
00175         BIO_free(out);
00176         ossl_raise(eX509CRLError, NULL);
00177     }
00178     BIO_get_mem_ptr(out, &buf);
00179     str = rb_str_new(buf->data, buf->length);
00180     BIO_free(out);
00181     return str;
00182 }
00183 
00184 static VALUE
00185 ossl_x509crl_get_issuer(VALUE self)
00186 {
00187     X509_CRL *crl;
00188 
00189     GetX509CRL(self, crl);
00190 
00191     return ossl_x509name_new(X509_CRL_get_issuer(crl)); /* NO DUP - don't free */
00192 }
00193 
00194 static VALUE
00195 ossl_x509crl_set_issuer(VALUE self, VALUE issuer)
00196 {
00197     X509_CRL *crl;
00198 
00199     GetX509CRL(self, crl);
00200 
00201     if (!X509_CRL_set_issuer_name(crl, GetX509NamePtr(issuer))) { /* DUPs name */
00202         ossl_raise(eX509CRLError, NULL);
00203     }
00204     return issuer;
00205 }
00206 
00207 static VALUE
00208 ossl_x509crl_get_last_update(VALUE self)
00209 {
00210     X509_CRL *crl;
00211 
00212     GetX509CRL(self, crl);
00213 
00214     return asn1time_to_time(X509_CRL_get_lastUpdate(crl));
00215 }
00216 
00217 static VALUE
00218 ossl_x509crl_set_last_update(VALUE self, VALUE time)
00219 {
00220     X509_CRL *crl;
00221     time_t sec;
00222 
00223     sec = time_to_time_t(time);
00224     GetX509CRL(self, crl);
00225     if (!X509_time_adj(crl->crl->lastUpdate, 0, &sec)) {
00226         ossl_raise(eX509CRLError, NULL);
00227     }
00228 
00229     return time;
00230 }
00231 
00232 static VALUE
00233 ossl_x509crl_get_next_update(VALUE self)
00234 {
00235     X509_CRL *crl;
00236 
00237     GetX509CRL(self, crl);
00238 
00239     return asn1time_to_time(X509_CRL_get_nextUpdate(crl));
00240 }
00241 
00242 static VALUE
00243 ossl_x509crl_set_next_update(VALUE self, VALUE time)
00244 {
00245     X509_CRL *crl;
00246     time_t sec;
00247 
00248     sec = time_to_time_t(time);
00249     GetX509CRL(self, crl);
00250     /* This must be some thinko in OpenSSL */
00251     if (!(crl->crl->nextUpdate = X509_time_adj(crl->crl->nextUpdate, 0, &sec))){
00252         ossl_raise(eX509CRLError, NULL);
00253     }
00254 
00255     return time;
00256 }
00257 
00258 static VALUE
00259 ossl_x509crl_get_revoked(VALUE self)
00260 {
00261     X509_CRL *crl;
00262     int i, num;
00263     X509_REVOKED *rev;
00264     VALUE ary, revoked;
00265 
00266     GetX509CRL(self, crl);
00267     num = sk_X509_REVOKED_num(X509_CRL_get_REVOKED(crl));
00268     if (num < 0) {
00269         OSSL_Debug("num < 0???");
00270         return rb_ary_new();
00271     }
00272     ary = rb_ary_new2(num);
00273     for(i=0; i<num; i++) {
00274         /* NO DUP - don't free! */
00275         rev = sk_X509_REVOKED_value(X509_CRL_get_REVOKED(crl), i);
00276         revoked = ossl_x509revoked_new(rev);
00277         rb_ary_push(ary, revoked);
00278     }
00279 
00280     return ary;
00281 }
00282 
00283 static VALUE
00284 ossl_x509crl_set_revoked(VALUE self, VALUE ary)
00285 {
00286     X509_CRL *crl;
00287     X509_REVOKED *rev;
00288     int i;
00289 
00290     Check_Type(ary, T_ARRAY);
00291     /* All ary members should be X509 Revoked */
00292     for (i=0; i<RARRAY_LEN(ary); i++) {
00293         OSSL_Check_Kind(RARRAY_PTR(ary)[i], cX509Rev);
00294     }
00295     GetX509CRL(self, crl);
00296     sk_X509_REVOKED_pop_free(crl->crl->revoked, X509_REVOKED_free);
00297     crl->crl->revoked = NULL;
00298     for (i=0; i<RARRAY_LEN(ary); i++) {
00299         rev = DupX509RevokedPtr(RARRAY_PTR(ary)[i]);
00300         if (!X509_CRL_add0_revoked(crl, rev)) { /* NO DUP - don't free! */
00301             ossl_raise(eX509CRLError, NULL);
00302         }
00303     }
00304     X509_CRL_sort(crl);
00305 
00306     return ary;
00307 }
00308 
00309 static VALUE
00310 ossl_x509crl_add_revoked(VALUE self, VALUE revoked)
00311 {
00312     X509_CRL *crl;
00313     X509_REVOKED *rev;
00314 
00315     GetX509CRL(self, crl);
00316     rev = DupX509RevokedPtr(revoked);
00317     if (!X509_CRL_add0_revoked(crl, rev)) { /* NO DUP - don't free! */
00318         ossl_raise(eX509CRLError, NULL);
00319     }
00320     X509_CRL_sort(crl);
00321 
00322     return revoked;
00323 }
00324 
00325 static VALUE
00326 ossl_x509crl_sign(VALUE self, VALUE key, VALUE digest)
00327 {
00328     X509_CRL *crl;
00329     EVP_PKEY *pkey;
00330     const EVP_MD *md;
00331 
00332     GetX509CRL(self, crl);
00333     pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */
00334     md = GetDigestPtr(digest);
00335     if (!X509_CRL_sign(crl, pkey, md)) {
00336         ossl_raise(eX509CRLError, NULL);
00337     }
00338 
00339     return self;
00340 }
00341 
00342 static VALUE
00343 ossl_x509crl_verify(VALUE self, VALUE key)
00344 {
00345     X509_CRL *crl;
00346     int ret;
00347 
00348     GetX509CRL(self, crl);
00349     if ((ret = X509_CRL_verify(crl, GetPKeyPtr(key))) < 0) {
00350         ossl_raise(eX509CRLError, NULL);
00351     }
00352     if (ret == 1) {
00353         return Qtrue;
00354     }
00355 
00356     return Qfalse;
00357 }
00358 
00359 static VALUE
00360 ossl_x509crl_to_der(VALUE self)
00361 {
00362     X509_CRL *crl;
00363     BIO *out;
00364     BUF_MEM *buf;
00365     VALUE str;
00366 
00367     GetX509CRL(self, crl);
00368     if (!(out = BIO_new(BIO_s_mem()))) {
00369         ossl_raise(eX509CRLError, NULL);
00370     }
00371     if (!i2d_X509_CRL_bio(out, crl)) {
00372         BIO_free(out);
00373         ossl_raise(eX509CRLError, NULL);
00374     }
00375     BIO_get_mem_ptr(out, &buf);
00376     str = rb_str_new(buf->data, buf->length);
00377     BIO_free(out);
00378 
00379     return str;
00380 }
00381 
00382 static VALUE
00383 ossl_x509crl_to_pem(VALUE self)
00384 {
00385     X509_CRL *crl;
00386     BIO *out;
00387     BUF_MEM *buf;
00388     VALUE str;
00389 
00390     GetX509CRL(self, crl);
00391     if (!(out = BIO_new(BIO_s_mem()))) {
00392         ossl_raise(eX509CRLError, NULL);
00393     }
00394     if (!PEM_write_bio_X509_CRL(out, crl)) {
00395         BIO_free(out);
00396         ossl_raise(eX509CRLError, NULL);
00397     }
00398     BIO_get_mem_ptr(out, &buf);
00399     str = rb_str_new(buf->data, buf->length);
00400     BIO_free(out);
00401 
00402     return str;
00403 }
00404 
00405 static VALUE
00406 ossl_x509crl_to_text(VALUE self)
00407 {
00408     X509_CRL *crl;
00409     BIO *out;
00410     BUF_MEM *buf;
00411     VALUE str;
00412 
00413     GetX509CRL(self, crl);
00414     if (!(out = BIO_new(BIO_s_mem()))) {
00415         ossl_raise(eX509CRLError, NULL);
00416     }
00417     if (!X509_CRL_print(out, crl)) {
00418         BIO_free(out);
00419         ossl_raise(eX509CRLError, NULL);
00420     }
00421     BIO_get_mem_ptr(out, &buf);
00422     str = rb_str_new(buf->data, buf->length);
00423     BIO_free(out);
00424 
00425     return str;
00426 }
00427 
00428 /*
00429  * Gets X509v3 extensions as array of X509Ext objects
00430  */
00431 static VALUE
00432 ossl_x509crl_get_extensions(VALUE self)
00433 {
00434     X509_CRL *crl;
00435     int count, i;
00436     X509_EXTENSION *ext;
00437     VALUE ary;
00438 
00439     GetX509CRL(self, crl);
00440     count = X509_CRL_get_ext_count(crl);
00441     if (count < 0) {
00442         OSSL_Debug("count < 0???");
00443         return rb_ary_new();
00444     }
00445     ary = rb_ary_new2(count);
00446     for (i=0; i<count; i++) {
00447         ext = X509_CRL_get_ext(crl, i); /* NO DUP - don't free! */
00448         rb_ary_push(ary, ossl_x509ext_new(ext));
00449     }
00450 
00451     return ary;
00452 }
00453 
00454 /*
00455  * Sets X509_EXTENSIONs
00456  */
00457 static VALUE
00458 ossl_x509crl_set_extensions(VALUE self, VALUE ary)
00459 {
00460     X509_CRL *crl;
00461     X509_EXTENSION *ext;
00462     int i;
00463 
00464     Check_Type(ary, T_ARRAY);
00465     /* All ary members should be X509 Extensions */
00466     for (i=0; i<RARRAY_LEN(ary); i++) {
00467         OSSL_Check_Kind(RARRAY_PTR(ary)[i], cX509Ext);
00468     }
00469     GetX509CRL(self, crl);
00470     sk_X509_EXTENSION_pop_free(crl->crl->extensions, X509_EXTENSION_free);
00471     crl->crl->extensions = NULL;
00472     for (i=0; i<RARRAY_LEN(ary); i++) {
00473         ext = DupX509ExtPtr(RARRAY_PTR(ary)[i]);
00474         if(!X509_CRL_add_ext(crl, ext, -1)) { /* DUPs ext - FREE it */
00475             X509_EXTENSION_free(ext);
00476             ossl_raise(eX509CRLError, NULL);
00477         }
00478         X509_EXTENSION_free(ext);
00479     }
00480 
00481     return ary;
00482 }
00483 
00484 static VALUE
00485 ossl_x509crl_add_extension(VALUE self, VALUE extension)
00486 {
00487     X509_CRL *crl;
00488     X509_EXTENSION *ext;
00489 
00490     GetX509CRL(self, crl);
00491     ext = DupX509ExtPtr(extension);
00492     if (!X509_CRL_add_ext(crl, ext, -1)) { /* DUPs ext - FREE it */
00493         X509_EXTENSION_free(ext);
00494         ossl_raise(eX509CRLError, NULL);
00495     }
00496     X509_EXTENSION_free(ext);
00497 
00498     return extension;
00499 }
00500 
00501 /*
00502  * INIT
00503  */
00504 void
00505 Init_ossl_x509crl()
00506 {
00507     eX509CRLError = rb_define_class_under(mX509, "CRLError", eOSSLError);
00508 
00509     cX509CRL = rb_define_class_under(mX509, "CRL", rb_cObject);
00510 
00511     rb_define_alloc_func(cX509CRL, ossl_x509crl_alloc);
00512     rb_define_method(cX509CRL, "initialize", ossl_x509crl_initialize, -1);
00513     rb_define_copy_func(cX509CRL, ossl_x509crl_copy);
00514 
00515     rb_define_method(cX509CRL, "version", ossl_x509crl_get_version, 0);
00516     rb_define_method(cX509CRL, "version=", ossl_x509crl_set_version, 1);
00517     rb_define_method(cX509CRL, "signature_algorithm", ossl_x509crl_get_signature_algorithm, 0);
00518     rb_define_method(cX509CRL, "issuer", ossl_x509crl_get_issuer, 0);
00519     rb_define_method(cX509CRL, "issuer=", ossl_x509crl_set_issuer, 1);
00520     rb_define_method(cX509CRL, "last_update", ossl_x509crl_get_last_update, 0);
00521     rb_define_method(cX509CRL, "last_update=", ossl_x509crl_set_last_update, 1);
00522     rb_define_method(cX509CRL, "next_update", ossl_x509crl_get_next_update, 0);
00523     rb_define_method(cX509CRL, "next_update=", ossl_x509crl_set_next_update, 1);
00524     rb_define_method(cX509CRL, "revoked", ossl_x509crl_get_revoked, 0);
00525     rb_define_method(cX509CRL, "revoked=", ossl_x509crl_set_revoked, 1);
00526     rb_define_method(cX509CRL, "add_revoked", ossl_x509crl_add_revoked, 1);
00527     rb_define_method(cX509CRL, "sign", ossl_x509crl_sign, 2);
00528     rb_define_method(cX509CRL, "verify", ossl_x509crl_verify, 1);
00529     rb_define_method(cX509CRL, "to_der", ossl_x509crl_to_der, 0);
00530     rb_define_method(cX509CRL, "to_pem", ossl_x509crl_to_pem, 0);
00531     rb_define_alias(cX509CRL, "to_s", "to_pem");
00532     rb_define_method(cX509CRL, "to_text", ossl_x509crl_to_text, 0);
00533     rb_define_method(cX509CRL, "extensions", ossl_x509crl_get_extensions, 0);
00534     rb_define_method(cX509CRL, "extensions=", ossl_x509crl_set_extensions, 1);
00535     rb_define_method(cX509CRL, "add_extension", ossl_x509crl_add_extension, 1);
00536 }
00537 
00538