Ruby 1.9.2p136(2010-12-25revision30365)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

# ext/openssl/ossl_x509req.c

Go to the documentation of this file.

    00001 /*
    00002  * $Id: ossl_x509req.c 27440 2010-04-22 08:21:01Z nobu $
    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 WrapX509Req(klass, obj, req) do { \
    00014     if (!req) { \
    00015         ossl_raise(rb_eRuntimeError, "Req wasn't initialized!"); \
    00016     } \
    00017     obj = Data_Wrap_Struct(klass, 0, X509_REQ_free, req); \
    00018 } while (0)
    00019 #define GetX509Req(obj, req) do { \
    00020     Data_Get_Struct(obj, X509_REQ, req); \
    00021     if (!req) { \
    00022         ossl_raise(rb_eRuntimeError, "Req wasn't initialized!"); \
    00023     } \
    00024 } while (0)
    00025 #define SafeGetX509Req(obj, req) do { \
    00026     OSSL_Check_Kind(obj, cX509Req); \
    00027     GetX509Req(obj, req); \
    00028 } while (0)
    00029
    00030 /*
    00031  * Classes
    00032  */
    00033 VALUE cX509Req;
    00034 VALUE eX509ReqError;
    00035
    00036 /*
    00037  * Public functions
    00038  */
    00039 VALUE
    00040 ossl_x509req_new(X509_REQ *req)
    00041 {
    00042     X509_REQ *new;
    00043     VALUE obj;
    00044
    00045     if (!req) {
    00046         new = X509_REQ_new();
    00047     } else {
    00048         new = X509_REQ_dup(req);
    00049     }
    00050     if (!new) {
    00051         ossl_raise(eX509ReqError, NULL);
    00052     }
    00053     WrapX509Req(cX509Req, obj, new);
    00054
    00055     return obj;
    00056 }
    00057
    00058 X509_REQ *
    00059 GetX509ReqPtr(VALUE obj)
    00060 {
    00061     X509_REQ *req;
    00062
    00063     SafeGetX509Req(obj, req);
    00064
    00065     return req;
    00066 }
    00067
    00068 X509_REQ *
    00069 DupX509ReqPtr(VALUE obj)
    00070 {
    00071     X509_REQ *req, *new;
    00072
    00073     SafeGetX509Req(obj, req);
    00074     if (!(new = X509_REQ_dup(req))) {
    00075         ossl_raise(eX509ReqError, NULL);
    00076     }
    00077
    00078     return new;
    00079 }
    00080
    00081 /*
    00082  * Private functions
    00083  */
    00084 static VALUE
    00085 ossl_x509req_alloc(VALUE klass)
    00086 {
    00087     X509_REQ *req;
    00088     VALUE obj;
    00089
    00090     if (!(req = X509_REQ_new())) {
    00091         ossl_raise(eX509ReqError, NULL);
    00092     }
    00093     WrapX509Req(klass, obj, req);
    00094
    00095     return obj;
    00096 }
    00097
    00098 static VALUE
    00099 ossl_x509req_initialize(int argc, VALUE *argv, VALUE self)
    00100 {
    00101     BIO *in;
    00102     X509_REQ *req, *x = DATA_PTR(self);
    00103     VALUE arg;
    00104
    00105     if (rb_scan_args(argc, argv, "01", &arg) == 0) {
    00106         return self;
    00107     }
    00108     arg = ossl_to_der_if_possible(arg);
    00109     in = ossl_obj2bio(arg);
    00110     req = PEM_read_bio_X509_REQ(in, &x, NULL, NULL);
    00111     DATA_PTR(self) = x;
    00112     if (!req) {
    00113         (void)BIO_reset(in);
    00114         req = d2i_X509_REQ_bio(in, &x);
    00115         DATA_PTR(self) = x;
    00116     }
    00117     BIO_free(in);
    00118     if (!req) ossl_raise(eX509ReqError, NULL);
    00119
    00120     return self;
    00121 }
    00122
    00123 static VALUE
    00124 ossl_x509req_copy(VALUE self, VALUE other)
    00125 {
    00126     X509_REQ *a, *b, *req;
    00127
    00128     rb_check_frozen(self);
    00129     if (self == other) return self;
    00130     GetX509Req(self, a);
    00131     SafeGetX509Req(other, b);
    00132     if (!(req = X509_REQ_dup(b))) {
    00133         ossl_raise(eX509ReqError, NULL);
    00134     }
    00135     X509_REQ_free(a);
    00136     DATA_PTR(self) = req;
    00137
    00138     return self;
    00139 }
    00140
    00141 static VALUE
    00142 ossl_x509req_to_pem(VALUE self)
    00143 {
    00144     X509_REQ *req;
    00145     BIO *out;
    00146     BUF_MEM *buf;
    00147     VALUE str;
    00148
    00149     GetX509Req(self, req);
    00150     if (!(out = BIO_new(BIO_s_mem()))) {
    00151         ossl_raise(eX509ReqError, NULL);
    00152     }
    00153     if (!PEM_write_bio_X509_REQ(out, req)) {
    00154         BIO_free(out);
    00155         ossl_raise(eX509ReqError, NULL);
    00156     }
    00157     BIO_get_mem_ptr(out, &buf);
    00158     str = rb_str_new(buf->data, buf->length);
    00159     BIO_free(out);
    00160
    00161     return str;
    00162 }
    00163
    00164 static VALUE
    00165 ossl_x509req_to_der(VALUE self)
    00166 {
    00167     X509_REQ *req;
    00168     VALUE str;
    00169     long len;
    00170     unsigned char *p;
    00171
    00172     GetX509Req(self, req);
    00173     if ((len = i2d_X509_REQ(req, NULL)) <= 0)
    00174         ossl_raise(eX509CertError, NULL);
    00175     str = rb_str_new(0, len);
    00176     p = (unsigned char *)RSTRING_PTR(str);
    00177     if (i2d_X509_REQ(req, &p) <= 0)
    00178         ossl_raise(eX509ReqError, NULL);
    00179     ossl_str_adjust(str, p);
    00180
    00181     return str;
    00182 }
    00183
    00184 static VALUE
    00185 ossl_x509req_to_text(VALUE self)
    00186 {
    00187     X509_REQ *req;
    00188     BIO *out;
    00189     BUF_MEM *buf;
    00190     VALUE str;
    00191
    00192     GetX509Req(self, req);
    00193     if (!(out = BIO_new(BIO_s_mem()))) {
    00194         ossl_raise(eX509ReqError, NULL);
    00195     }
    00196     if (!X509_REQ_print(out, req)) {
    00197         BIO_free(out);
    00198         ossl_raise(eX509ReqError, NULL);
    00199     }
    00200     BIO_get_mem_ptr(out, &buf);
    00201     str = rb_str_new(buf->data, buf->length);
    00202     BIO_free(out);
    00203
    00204     return str;
    00205 }
    00206
    00207 #if 0
    00208 /*
    00209  * Makes X509 from X509_REQuest
    00210  */
    00211 static VALUE
    00212 ossl_x509req_to_x509(VALUE self, VALUE days, VALUE key)
    00213 {
    00214     X509_REQ *req;
    00215     X509 *x509;
    00216
    00217     GetX509Req(self, req);
    00218     ...
    00219     if (!(x509 = X509_REQ_to_X509(req, d, pkey))) {
    00220         ossl_raise(eX509ReqError, NULL);
    00221     }
    00222
    00223     return ossl_x509_new(x509);
    00224 }
    00225 #endif
    00226
    00227 static VALUE
    00228 ossl_x509req_get_version(VALUE self)
    00229 {
    00230     X509_REQ *req;
    00231     long version;
    00232
    00233     GetX509Req(self, req);
    00234     version = X509_REQ_get_version(req);
    00235
    00236     return LONG2FIX(version);
    00237 }
    00238
    00239 static VALUE
    00240 ossl_x509req_set_version(VALUE self, VALUE version)
    00241 {
    00242     X509_REQ *req;
    00243     long ver;
    00244
    00245     if ((ver = FIX2LONG(version)) < 0) {
    00246         ossl_raise(eX509ReqError, "version must be >= 0!");
    00247     }
    00248     GetX509Req(self, req);
    00249     if (!X509_REQ_set_version(req, ver)) {
    00250         ossl_raise(eX509ReqError, NULL);
    00251     }
    00252
    00253     return version;
    00254 }
    00255
    00256 static VALUE
    00257 ossl_x509req_get_subject(VALUE self)
    00258 {
    00259     X509_REQ *req;
    00260     X509_NAME *name;
    00261
    00262     GetX509Req(self, req);
    00263     if (!(name = X509_REQ_get_subject_name(req))) { /* NO DUP - don't free */
    00264         ossl_raise(eX509ReqError, NULL);
    00265     }
    00266
    00267     return ossl_x509name_new(name);
    00268 }
    00269
    00270 static VALUE
    00271 ossl_x509req_set_subject(VALUE self, VALUE subject)
    00272 {
    00273     X509_REQ *req;
    00274
    00275     GetX509Req(self, req);
    00276     /* DUPs name */
    00277     if (!X509_REQ_set_subject_name(req, GetX509NamePtr(subject))) {
    00278         ossl_raise(eX509ReqError, NULL);
    00279     }
    00280
    00281     return subject;
    00282 }
    00283
    00284 static VALUE
    00285 ossl_x509req_get_signature_algorithm(VALUE self)
    00286 {
    00287     X509_REQ *req;
    00288     BIO *out;
    00289     BUF_MEM *buf;
    00290     VALUE str;
    00291
    00292     GetX509Req(self, req);
    00293
    00294     if (!(out = BIO_new(BIO_s_mem()))) {
    00295         ossl_raise(eX509ReqError, NULL);
    00296     }
    00297     if (!i2a_ASN1_OBJECT(out, req->sig_alg->algorithm)) {
    00298         BIO_free(out);
    00299         ossl_raise(eX509ReqError, NULL);
    00300     }
    00301     BIO_get_mem_ptr(out, &buf);
    00302     str = rb_str_new(buf->data, buf->length);
    00303     BIO_free(out);
    00304     return str;
    00305 }
    00306
    00307 static VALUE
    00308 ossl_x509req_get_public_key(VALUE self)
    00309 {
    00310     X509_REQ *req;
    00311     EVP_PKEY *pkey;
    00312
    00313     GetX509Req(self, req);
    00314     if (!(pkey = X509_REQ_get_pubkey(req))) { /* adds reference */
    00315         ossl_raise(eX509ReqError, NULL);
    00316     }
    00317
    00318     return ossl_pkey_new(pkey); /* NO DUP - OK */
    00319 }
    00320
    00321 static VALUE
    00322 ossl_x509req_set_public_key(VALUE self, VALUE key)
    00323 {
    00324     X509_REQ *req;
    00325     EVP_PKEY *pkey;
    00326
    00327     GetX509Req(self, req);
    00328     pkey = GetPKeyPtr(key); /* NO NEED TO DUP */
    00329     if (!X509_REQ_set_pubkey(req, pkey)) {
    00330         ossl_raise(eX509ReqError, NULL);
    00331     }
    00332
    00333     return key;
    00334 }
    00335
    00336 static VALUE
    00337 ossl_x509req_sign(VALUE self, VALUE key, VALUE digest)
    00338 {
    00339     X509_REQ *req;
    00340     EVP_PKEY *pkey;
    00341     const EVP_MD *md;
    00342
    00343     GetX509Req(self, req);
    00344     pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */
    00345     md = GetDigestPtr(digest);
    00346     if (!X509_REQ_sign(req, pkey, md)) {
    00347         ossl_raise(eX509ReqError, NULL);
    00348     }
    00349
    00350     return self;
    00351 }
    00352
    00353 /*
    00354  * Checks that cert signature is made with PRIVversion of this PUBLIC 'key'
    00355  */
    00356 static VALUE
    00357 ossl_x509req_verify(VALUE self, VALUE key)
    00358 {
    00359     X509_REQ *req;
    00360     EVP_PKEY *pkey;
    00361     int i;
    00362
    00363     GetX509Req(self, req);
    00364     pkey = GetPKeyPtr(key); /* NO NEED TO DUP */
    00365     if ((i = X509_REQ_verify(req, pkey)) < 0) {
    00366         ossl_raise(eX509ReqError, NULL);
    00367     }
    00368     if (i > 0) {
    00369         return Qtrue;
    00370     }
    00371
    00372     return Qfalse;
    00373 }
    00374
    00375 static VALUE
    00376 ossl_x509req_get_attributes(VALUE self)
    00377 {
    00378     X509_REQ *req;
    00379     int count, i;
    00380     X509_ATTRIBUTE *attr;
    00381     VALUE ary;
    00382
    00383     GetX509Req(self, req);
    00384
    00385     count = X509_REQ_get_attr_count(req);
    00386     if (count < 0) {
    00387         OSSL_Debug("count < 0???");
    00388         return rb_ary_new();
    00389     }
    00390     ary = rb_ary_new2(count);
    00391     for (i=0; i<count; i++) {
    00392         attr = X509_REQ_get_attr(req, i);
    00393         rb_ary_push(ary, ossl_x509attr_new(attr));
    00394     }
    00395
    00396     return ary;
    00397 }
    00398
    00399 static VALUE
    00400 ossl_x509req_set_attributes(VALUE self, VALUE ary)
    00401 {
    00402     X509_REQ *req;
    00403     X509_ATTRIBUTE *attr;
    00404     int i;
    00405     VALUE item;
    00406
    00407     Check_Type(ary, T_ARRAY);
    00408     for (i=0;i<RARRAY_LEN(ary); i++) {
    00409         OSSL_Check_Kind(RARRAY_PTR(ary)[i], cX509Attr);
    00410     }
    00411     GetX509Req(self, req);
    00412     sk_X509_ATTRIBUTE_pop_free(req->req_info->attributes, X509_ATTRIBUTE_free);
    00413     req->req_info->attributes = NULL;
    00414     for (i=0;i<RARRAY_LEN(ary); i++) {
    00415         item = RARRAY_PTR(ary)[i];
    00416         attr = DupX509AttrPtr(item);
    00417         if (!X509_REQ_add1_attr(req, attr)) {
    00418             ossl_raise(eX509ReqError, NULL);
    00419         }
    00420     }
    00421     return ary;
    00422 }
    00423
    00424 static VALUE
    00425 ossl_x509req_add_attribute(VALUE self, VALUE attr)
    00426 {
    00427     X509_REQ *req;
    00428
    00429     GetX509Req(self, req);
    00430     if (!X509_REQ_add1_attr(req, DupX509AttrPtr(attr))) {
    00431         ossl_raise(eX509ReqError, NULL);
    00432     }
    00433
    00434     return attr;
    00435 }
    00436
    00437 /*
    00438  * X509_REQUEST init
    00439  */
    00440 void
    00441 Init_ossl_x509req()
    00442 {
    00443     eX509ReqError = rb_define_class_under(mX509, "RequestError", eOSSLError);
    00444
    00445     cX509Req = rb_define_class_under(mX509, "Request", rb_cObject);
    00446
    00447     rb_define_alloc_func(cX509Req, ossl_x509req_alloc);
    00448     rb_define_method(cX509Req, "initialize", ossl_x509req_initialize, -1);
    00449     rb_define_copy_func(cX509Req, ossl_x509req_copy);
    00450
    00451     rb_define_method(cX509Req, "to_pem", ossl_x509req_to_pem, 0);
    00452     rb_define_method(cX509Req, "to_der", ossl_x509req_to_der, 0);
    00453     rb_define_alias(cX509Req, "to_s", "to_pem");
    00454     rb_define_method(cX509Req, "to_text", ossl_x509req_to_text, 0);
    00455     rb_define_method(cX509Req, "version", ossl_x509req_get_version, 0);
    00456     rb_define_method(cX509Req, "version=", ossl_x509req_set_version, 1);
    00457     rb_define_method(cX509Req, "subject", ossl_x509req_get_subject, 0);
    00458     rb_define_method(cX509Req, "subject=", ossl_x509req_set_subject, 1);
    00459     rb_define_method(cX509Req, "signature_algorithm", ossl_x509req_get_signature_algorithm, 0);
    00460     rb_define_method(cX509Req, "public_key", ossl_x509req_get_public_key, 0);
    00461     rb_define_method(cX509Req, "public_key=", ossl_x509req_set_public_key, 1);
    00462     rb_define_method(cX509Req, "sign", ossl_x509req_sign, 2);
    00463     rb_define_method(cX509Req, "verify", ossl_x509req_verify, 1);
    00464     rb_define_method(cX509Req, "attributes", ossl_x509req_get_attributes, 0);
    00465     rb_define_method(cX509Req, "attributes=", ossl_x509req_set_attributes, 1);
    00466     rb_define_method(cX509Req, "add_attribute", ossl_x509req_add_attribute, 1);
    00467 }
    00468
    00469