Ruby 1.9.3p327(2012-11-10revision37606)
|
00001 /* 00002 * $Id: ossl_x509attr.c 31103 2011-03-13 09:11:45Z akr $ 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