00001
00002
00003
00004
00005
00006
00007
00008
00009
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
00032
00033 VALUE cX509Attr;
00034 VALUE eX509AttrError;
00035
00036
00037
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
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
00089
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
00118
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
00139
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
00174
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
00201
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
00237
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
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