• 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 

Generated on Wed Sep 8 2010 09:55:24 for Ruby by  doxygen 1.7.1