Ruby 1.9.2p136(2010-12-25revision30365)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

# ext/openssl/ossl_x509attr.c

Go to the documentation of this file.

    00001 /*
    00002  * $Id: ossl_x509attr.c 27437 2010-04-22 08:04:13Z nobu $
    00003  * 'OpenSSL for Ruby' project
    00004  * Copyright (C) 2001 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 WrapX509Attr(klass, obj, attr) do { \
    00014     if (!attr) { \
    00015         ossl_raise(rb_eRuntimeError, "ATTR wasn't initialized!"); \
    00016     } \
    00017     obj = Data_Wrap_Struct(klass, 0, X509_ATTRIBUTE_free, attr); \
    00018 } while (0)
    00019 #define GetX509Attr(obj, attr) do { \
    00020     Data_Get_Struct(obj, X509_ATTRIBUTE, attr); \
    00021     if (!attr) { \
    00022         ossl_raise(rb_eRuntimeError, "ATTR wasn't initialized!"); \
    00023     } \
    00024 } while (0)
    00025 #define SafeGetX509Attr(obj, attr) do { \
    00026     OSSL_Check_Kind(obj, cX509Attr); \
    00027     GetX509Attr(obj, attr); \
    00028 } while (0)
    00029
    00030 /*
    00031  * Classes
    00032  */
    00033 VALUE cX509Attr;
    00034 VALUE eX509AttrError;
    00035
    00036 /*
    00037  * Public
    00038  */
    00039 VALUE
    00040 ossl_x509attr_new(X509_ATTRIBUTE *attr)
    00041 {
    00042     X509_ATTRIBUTE *new;
    00043     VALUE obj;
    00044
    00045     if (!attr) {
    00046         new = X509_ATTRIBUTE_new();
    00047     } else {
    00048         new = X509_ATTRIBUTE_dup(attr);
    00049     }
    00050     if (!new) {
    00051         ossl_raise(eX509AttrError, NULL);
    00052     }
    00053     WrapX509Attr(cX509Attr, obj, new);
    00054
    00055     return obj;
    00056 }
    00057
    00058 X509_ATTRIBUTE *
    00059 DupX509AttrPtr(VALUE obj)
    00060 {
    00061     X509_ATTRIBUTE *attr, *new;
    00062
    00063     SafeGetX509Attr(obj, attr);
    00064     if (!(new = X509_ATTRIBUTE_dup(attr))) {
    00065         ossl_raise(eX509AttrError, NULL);
    00066     }
    00067
    00068     return new;
    00069 }
    00070
    00071 /*
    00072  * Private
    00073  */
    00074 static VALUE
    00075 ossl_x509attr_alloc(VALUE klass)
    00076 {
    00077     X509_ATTRIBUTE *attr;
    00078     VALUE obj;
    00079
    00080     if (!(attr = X509_ATTRIBUTE_new()))
    00081         ossl_raise(eX509AttrError, NULL);
    00082     WrapX509Attr(klass, obj, attr);
    00083
    00084     return obj;
    00085 }
    00086
    00087 /*
    00088  * call-seq:
    00089  *    Attribute.new(oid [, value]) => attr
    00090  */
    00091 static VALUE
    00092 ossl_x509attr_initialize(int argc, VALUE *argv, VALUE self)
    00093 {
    00094     VALUE oid, value;
    00095     X509_ATTRIBUTE *attr, *x;
    00096     const unsigned char *p;
    00097
    00098     GetX509Attr(self, attr);
    00099     if(rb_scan_args(argc, argv, "11", &oid, &value) == 1){
    00100         oid = ossl_to_der_if_possible(oid);
    00101         StringValue(oid);
    00102         p = (unsigned char *)RSTRING_PTR(oid);
    00103         x = d2i_X509_ATTRIBUTE(&attr, &p, RSTRING_LEN(oid));
    00104         DATA_PTR(self) = attr;
    00105         if(!x){
    00106             ossl_raise(eX509AttrError, NULL);
    00107         }
    00108         return self;
    00109     }
    00110     rb_funcall(self, rb_intern("oid="), 1, oid);
    00111     rb_funcall(self, rb_intern("value="), 1, value);
    00112
    00113     return self;
    00114 }
    00115
    00116 /*
    00117  * call-seq:
    00118  *    attr.oid = string => string
    00119  */
    00120 static VALUE
    00121 ossl_x509attr_set_oid(VALUE self, VALUE oid)
    00122 {
    00123     X509_ATTRIBUTE *attr;
    00124     ASN1_OBJECT *obj;
    00125     char *s;
    00126
    00127     s = StringValuePtr(oid);
    00128     obj = OBJ_txt2obj(s, 0);
    00129     if(!obj) obj = OBJ_txt2obj(s, 1);
    00130     if(!obj) ossl_raise(eX509AttrError, NULL);
    00131     GetX509Attr(self, attr);
    00132     X509_ATTRIBUTE_set1_object(attr, obj);
    00133
    00134     return oid;
    00135 }
    00136
    00137 /*
    00138  * call-seq:
    00139  *    attr.oid => string
    00140  */
    00141 static VALUE
    00142 ossl_x509attr_get_oid(VALUE self)
    00143 {
    00144     X509_ATTRIBUTE *attr;
    00145     ASN1_OBJECT *oid;
    00146     BIO *out;
    00147     VALUE ret;
    00148     int nid;
    00149
    00150     GetX509Attr(self, attr);
    00151     oid = X509_ATTRIBUTE_get0_object(attr);
    00152     if ((nid = OBJ_obj2nid(oid)) != NID_undef)
    00153         ret = rb_str_new2(OBJ_nid2sn(nid));
    00154     else{
    00155         if (!(out = BIO_new(BIO_s_mem())))
    00156             ossl_raise(eX509AttrError, NULL);
    00157         i2a_ASN1_OBJECT(out, oid);
    00158         ret = ossl_membio2str(out);
    00159     }
    00160
    00161     return ret;
    00162 }
    00163
    00164 #if defined(HAVE_ST_X509_ATTRIBUTE_SINGLE) || defined(HAVE_ST_SINGLE)
    00165 #  define OSSL_X509ATTR_IS_SINGLE(attr)  ((attr)->single)
    00166 #  define OSSL_X509ATTR_SET_SINGLE(attr) ((attr)->single = 1)
    00167 #else
    00168 #  define OSSL_X509ATTR_IS_SINGLE(attr)  (!(attr)->set)
    00169 #  define OSSL_X509ATTR_SET_SINGLE(attr) ((attr)->set = 0)
    00170 #endif
    00171
    00172 /*
    00173  * call-seq:
    00174  *    attr.value = asn1 => asn1
    00175  */
    00176 static VALUE
    00177 ossl_x509attr_set_value(VALUE self, VALUE value)
    00178 {
    00179     X509_ATTRIBUTE *attr;
    00180     ASN1_TYPE *a1type;
    00181
    00182     if(!(a1type = ossl_asn1_get_asn1type(value)))
    00183         ossl_raise(eASN1Error, "could not get ASN1_TYPE");
    00184     if(ASN1_TYPE_get(a1type) == V_ASN1_SEQUENCE){
    00185         ASN1_TYPE_free(a1type);
    00186         ossl_raise(eASN1Error, "couldn't set SEQUENCE for attribute value.");
    00187     }
    00188     GetX509Attr(self, attr);
    00189     if(attr->value.set){
    00190         if(OSSL_X509ATTR_IS_SINGLE(attr)) ASN1_TYPE_free(attr->value.single);
    00191         else sk_ASN1_TYPE_free(attr->value.set);
    00192     }
    00193     OSSL_X509ATTR_SET_SINGLE(attr);
    00194     attr->value.single = a1type;
    00195
    00196     return value;
    00197 }
    00198
    00199 /*
    00200  * call-seq:
    00201  *    attr.value => asn1
    00202  */
    00203 static VALUE
    00204 ossl_x509attr_get_value(VALUE self)
    00205 {
    00206     X509_ATTRIBUTE *attr;
    00207     VALUE str, asn1;
    00208     long length;
    00209     unsigned char *p;
    00210
    00211     GetX509Attr(self, attr);
    00212     if(attr->value.ptr == NULL) return Qnil;
    00213     if(OSSL_X509ATTR_IS_SINGLE(attr)){
    00214         length = i2d_ASN1_TYPE(attr->value.single, NULL);
    00215         str = rb_str_new(0, length);
    00216         p = (unsigned char *)RSTRING_PTR(str);
    00217         i2d_ASN1_TYPE(attr->value.single, &p);
    00218         ossl_str_adjust(str, p);
    00219     }
    00220     else{
    00221         length = i2d_ASN1_SET_OF_ASN1_TYPE(attr->value.set,
    00222                         (unsigned char **) NULL, i2d_ASN1_TYPE,
    00223                         V_ASN1_SET, V_ASN1_UNIVERSAL, 0);
    00224         str = rb_str_new(0, length);
    00225         p = (unsigned char *)RSTRING_PTR(str);
    00226         i2d_ASN1_SET_OF_ASN1_TYPE(attr->value.set, &p,
    00227                         i2d_ASN1_TYPE, V_ASN1_SET, V_ASN1_UNIVERSAL, 0);
    00228         ossl_str_adjust(str, p);
    00229     }
    00230     asn1 = rb_funcall(mASN1, rb_intern("decode"), 1, str);
    00231
    00232     return asn1;
    00233 }
    00234
    00235 /*
    00236  * call-seq:
    00237  *    attr.to_der => string
    00238  */
    00239 static VALUE
    00240 ossl_x509attr_to_der(VALUE self)
    00241 {
    00242     X509_ATTRIBUTE *attr;
    00243     VALUE str;
    00244     int len;
    00245     unsigned char *p;
    00246
    00247     GetX509Attr(self, attr);
    00248     if((len = i2d_X509_ATTRIBUTE(attr, NULL)) <= 0)
    00249         ossl_raise(eX509AttrError, NULL);
    00250     str = rb_str_new(0, len);
    00251     p = (unsigned char *)RSTRING_PTR(str);
    00252     if(i2d_X509_ATTRIBUTE(attr, &p) <= 0)
    00253         ossl_raise(eX509AttrError, NULL);
    00254     rb_str_set_len(str, p - (unsigned char*)RSTRING_PTR(str));
    00255
    00256     return str;
    00257 }
    00258
    00259 /*
    00260  * X509_ATTRIBUTE init
    00261  */
    00262 void
    00263 Init_ossl_x509attr()
    00264 {
    00265     eX509AttrError = rb_define_class_under(mX509, "AttributeError", eOSSLError);
    00266
    00267     cX509Attr = rb_define_class_under(mX509, "Attribute", rb_cObject);
    00268     rb_define_alloc_func(cX509Attr, ossl_x509attr_alloc);
    00269     rb_define_method(cX509Attr, "initialize", ossl_x509attr_initialize, -1);
    00270     rb_define_method(cX509Attr, "oid=", ossl_x509attr_set_oid, 1);
    00271     rb_define_method(cX509Attr, "oid", ossl_x509attr_get_oid, 0);
    00272     rb_define_method(cX509Attr, "value=", ossl_x509attr_set_value, 1);
    00273     rb_define_method(cX509Attr, "value", ossl_x509attr_get_value, 0);
    00274     rb_define_method(cX509Attr, "to_der", ossl_x509attr_to_der, 0);
    00275 }
    00276