2 * $Id: ossl_x509attr.c 11708 2007-02-12 23:01:19Z shyouhei $
3 * 'OpenSSL for Ruby' project
4 * Copyright (C) 2001 Michal Rokos <m.rokos@sh.cvut.cz>
8 * This program is licenced under the same licence as Ruby.
9 * (See the file 'LICENCE'.)
13 #define WrapX509Attr(klass, obj, attr) do { \
15 ossl_raise(rb_eRuntimeError, "ATTR wasn't initialized!"); \
17 obj = Data_Wrap_Struct(klass, 0, X509_ATTRIBUTE_free, attr); \
19 #define GetX509Attr(obj, attr) do { \
20 Data_Get_Struct(obj, X509_ATTRIBUTE, attr); \
22 ossl_raise(rb_eRuntimeError, "ATTR wasn't initialized!"); \
25 #define SafeGetX509Attr(obj, attr) do { \
26 OSSL_Check_Kind(obj, cX509Attr); \
27 GetX509Attr(obj, attr); \
40 ossl_x509attr_new(X509_ATTRIBUTE
*attr
)
46 new = X509_ATTRIBUTE_new();
48 new = X509_ATTRIBUTE_dup(attr
);
51 ossl_raise(eX509AttrError
, NULL
);
53 WrapX509Attr(cX509Attr
, obj
, new);
59 DupX509AttrPtr(VALUE obj
)
61 X509_ATTRIBUTE
*attr
, *new;
63 SafeGetX509Attr(obj
, attr
);
64 if (!(new = X509_ATTRIBUTE_dup(attr
))) {
65 ossl_raise(eX509AttrError
, NULL
);
75 ossl_x509attr_alloc(VALUE klass
)
80 if (!(attr
= X509_ATTRIBUTE_new()))
81 ossl_raise(eX509AttrError
, NULL
);
82 WrapX509Attr(klass
, obj
, attr
);
88 ossl_x509attr_initialize(int argc
, VALUE
*argv
, VALUE self
)
94 GetX509Attr(self
, attr
);
95 if(rb_scan_args(argc
, argv
, "11", &oid
, &value
) == 1){
96 oid
= ossl_to_der_if_possible(oid
);
98 p
= RSTRING(oid
)->ptr
;
99 if(!d2i_X509_ATTRIBUTE((X509_ATTRIBUTE
**)&DATA_PTR(self
),
100 &p
, RSTRING(oid
)->len
)){
101 ossl_raise(eX509AttrError
, NULL
);
105 rb_funcall(self
, rb_intern("oid="), 1, oid
);
106 rb_funcall(self
, rb_intern("value="), 1, value
);
112 ossl_x509attr_set_oid(VALUE self
, VALUE oid
)
114 X509_ATTRIBUTE
*attr
;
118 s
= StringValuePtr(oid
);
119 obj
= OBJ_txt2obj(s
, 0);
120 if(!obj
) obj
= OBJ_txt2obj(s
, 1);
121 if(!obj
) ossl_raise(eX509AttrError
, NULL
);
122 GetX509Attr(self
, attr
);
123 X509_ATTRIBUTE_set1_object(attr
, obj
);
129 ossl_x509attr_get_oid(VALUE self
)
131 X509_ATTRIBUTE
*attr
;
137 GetX509Attr(self
, attr
);
138 oid
= X509_ATTRIBUTE_get0_object(attr
);
139 if ((nid
= OBJ_obj2nid(oid
)) != NID_undef
)
140 ret
= rb_str_new2(OBJ_nid2sn(nid
));
142 if (!(out
= BIO_new(BIO_s_mem())))
143 ossl_raise(eX509AttrError
, NULL
);
144 i2a_ASN1_OBJECT(out
, oid
);
145 ret
= ossl_membio2str(out
);
151 #if defined(HAVE_ST_X509_ATTRIBUTE_SINGLE) || defined(HAVE_ST_SINGLE)
152 # define OSSL_X509ATTR_IS_SINGLE(attr) ((attr)->single)
153 # define OSSL_X509ATTR_SET_SINGLE(attr) ((attr)->single = 1)
155 # define OSSL_X509ATTR_IS_SINGLE(attr) (!(attr)->set)
156 # define OSSL_X509ATTR_SET_SINGLE(attr) ((attr)->set = 0)
160 ossl_x509attr_set_value(VALUE self
, VALUE value
)
162 X509_ATTRIBUTE
*attr
;
165 if(!(a1type
= ossl_asn1_get_asn1type(value
)))
166 ossl_raise(eASN1Error
, "could not get ASN1_TYPE");
167 if(ASN1_TYPE_get(a1type
) == V_ASN1_SEQUENCE
){
168 ASN1_TYPE_free(a1type
);
169 ossl_raise(eASN1Error
, "couldn't set SEQUENCE for attribute value.");
171 GetX509Attr(self
, attr
);
173 if(OSSL_X509ATTR_IS_SINGLE(attr
)) ASN1_TYPE_free(attr
->value
.single
);
174 else sk_ASN1_TYPE_free(attr
->value
.set
);
176 OSSL_X509ATTR_SET_SINGLE(attr
);
177 attr
->value
.single
= a1type
;
183 ossl_x509attr_get_value(VALUE self
)
185 X509_ATTRIBUTE
*attr
;
190 GetX509Attr(self
, attr
);
191 if(attr
->value
.ptr
== NULL
) return Qnil
;
192 if(OSSL_X509ATTR_IS_SINGLE(attr
)){
193 length
= i2d_ASN1_TYPE(attr
->value
.single
, NULL
);
194 str
= rb_str_new(0, length
);
195 p
= RSTRING(str
)->ptr
;
196 i2d_ASN1_TYPE(attr
->value
.single
, &p
);
197 ossl_str_adjust(str
, p
);
200 length
= i2d_ASN1_SET_OF_ASN1_TYPE(attr
->value
.set
, NULL
,
201 i2d_ASN1_TYPE
, V_ASN1_SET
, V_ASN1_UNIVERSAL
, 0);
202 str
= rb_str_new(0, length
);
203 p
= RSTRING(str
)->ptr
;
204 i2d_ASN1_SET_OF_ASN1_TYPE(attr
->value
.set
, &p
,
205 i2d_ASN1_TYPE
, V_ASN1_SET
, V_ASN1_UNIVERSAL
, 0);
206 ossl_str_adjust(str
, p
);
208 asn1
= rb_funcall(mASN1
, rb_intern("decode"), 1, str
);
214 ossl_x509attr_to_der(VALUE self
)
216 X509_ATTRIBUTE
*attr
;
221 GetX509Attr(self
, attr
);
222 if((len
= i2d_X509_ATTRIBUTE(attr
, NULL
)) <= 0)
223 ossl_raise(eX509AttrError
, NULL
);
224 str
= rb_str_new(0, len
);
225 p
= RSTRING(str
)->ptr
;
226 if(i2d_X509_ATTRIBUTE(attr
, &p
) <= 0)
227 ossl_raise(eX509AttrError
, NULL
);
228 RSTRING(str
)->len
= p
- (unsigned char*)RSTRING(str
)->ptr
;
234 * X509_ATTRIBUTE init
239 eX509AttrError
= rb_define_class_under(mX509
, "AttributeError", eOSSLError
);
241 cX509Attr
= rb_define_class_under(mX509
, "Attribute", rb_cObject
);
242 rb_define_alloc_func(cX509Attr
, ossl_x509attr_alloc
);
243 rb_define_method(cX509Attr
, "initialize", ossl_x509attr_initialize
, -1);
244 rb_define_method(cX509Attr
, "oid=", ossl_x509attr_set_oid
, 1);
245 rb_define_method(cX509Attr
, "oid", ossl_x509attr_get_oid
, 0);
246 rb_define_method(cX509Attr
, "value=", ossl_x509attr_set_value
, 1);
247 rb_define_method(cX509Attr
, "value", ossl_x509attr_get_value
, 0);
248 rb_define_method(cX509Attr
, "to_der", ossl_x509attr_to_der
, 0);