Updated MSpec source to 1c3ee1c8.
[rbx.git] / stdlib / ext / openssl / ossl_x509attr.c
blob94d8ff07ed740a11a496a96c8158a40aee60ba99
1 /*
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>
5 * All rights reserved.
6 */
7 /*
8 * This program is licenced under the same licence as Ruby.
9 * (See the file 'LICENCE'.)
11 #include "ossl.h"
13 #define WrapX509Attr(klass, obj, attr) do { \
14 if (!attr) { \
15 ossl_raise(rb_eRuntimeError, "ATTR wasn't initialized!"); \
16 } \
17 obj = Data_Wrap_Struct(klass, 0, X509_ATTRIBUTE_free, attr); \
18 } while (0)
19 #define GetX509Attr(obj, attr) do { \
20 Data_Get_Struct(obj, X509_ATTRIBUTE, attr); \
21 if (!attr) { \
22 ossl_raise(rb_eRuntimeError, "ATTR wasn't initialized!"); \
23 } \
24 } while (0)
25 #define SafeGetX509Attr(obj, attr) do { \
26 OSSL_Check_Kind(obj, cX509Attr); \
27 GetX509Attr(obj, attr); \
28 } while (0)
31 * Classes
33 VALUE cX509Attr;
34 VALUE eX509AttrError;
37 * Public
39 VALUE
40 ossl_x509attr_new(X509_ATTRIBUTE *attr)
42 X509_ATTRIBUTE *new;
43 VALUE obj;
45 if (!attr) {
46 new = X509_ATTRIBUTE_new();
47 } else {
48 new = X509_ATTRIBUTE_dup(attr);
50 if (!new) {
51 ossl_raise(eX509AttrError, NULL);
53 WrapX509Attr(cX509Attr, obj, new);
55 return obj;
58 X509_ATTRIBUTE *
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);
68 return new;
72 * Private
74 static VALUE
75 ossl_x509attr_alloc(VALUE klass)
77 X509_ATTRIBUTE *attr;
78 VALUE obj;
80 if (!(attr = X509_ATTRIBUTE_new()))
81 ossl_raise(eX509AttrError, NULL);
82 WrapX509Attr(klass, obj, attr);
84 return obj;
87 static VALUE
88 ossl_x509attr_initialize(int argc, VALUE *argv, VALUE self)
90 VALUE oid, value;
91 X509_ATTRIBUTE *attr;
92 unsigned char *p;
94 GetX509Attr(self, attr);
95 if(rb_scan_args(argc, argv, "11", &oid, &value) == 1){
96 oid = ossl_to_der_if_possible(oid);
97 StringValue(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);
103 return self;
105 rb_funcall(self, rb_intern("oid="), 1, oid);
106 rb_funcall(self, rb_intern("value="), 1, value);
108 return self;
111 static VALUE
112 ossl_x509attr_set_oid(VALUE self, VALUE oid)
114 X509_ATTRIBUTE *attr;
115 ASN1_OBJECT *obj;
116 char *s;
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);
125 return oid;
128 static VALUE
129 ossl_x509attr_get_oid(VALUE self)
131 X509_ATTRIBUTE *attr;
132 ASN1_OBJECT *oid;
133 BIO *out;
134 VALUE ret;
135 int nid;
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));
141 else{
142 if (!(out = BIO_new(BIO_s_mem())))
143 ossl_raise(eX509AttrError, NULL);
144 i2a_ASN1_OBJECT(out, oid);
145 ret = ossl_membio2str(out);
148 return ret;
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)
154 #else
155 # define OSSL_X509ATTR_IS_SINGLE(attr) (!(attr)->set)
156 # define OSSL_X509ATTR_SET_SINGLE(attr) ((attr)->set = 0)
157 #endif
159 static VALUE
160 ossl_x509attr_set_value(VALUE self, VALUE value)
162 X509_ATTRIBUTE *attr;
163 ASN1_TYPE *a1type;
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);
172 if(attr->value.set){
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;
179 return value;
182 static VALUE
183 ossl_x509attr_get_value(VALUE self)
185 X509_ATTRIBUTE *attr;
186 VALUE str, asn1;
187 long length;
188 unsigned char *p;
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);
199 else{
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);
210 return asn1;
213 static VALUE
214 ossl_x509attr_to_der(VALUE self)
216 X509_ATTRIBUTE *attr;
217 VALUE str;
218 int len;
219 unsigned char *p;
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;
230 return str;
234 * X509_ATTRIBUTE init
236 void
237 Init_ossl_x509attr()
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);