Ruby 2.7.0p0(2019-12-25revision647ee6f091eafcce70ffb75ddf7e121e192ab217)

ossl_x509attr.c
Go to the documentation of this file.
1 /*
2 * 'OpenSSL for Ruby' project
3 * Copyright (C) 2001 Michal Rokos <m.rokos@sh.cvut.cz>
4 * All rights reserved.
5 */
6 /*
7 * This program is licensed under the same licence as Ruby.
8 * (See the file 'LICENCE'.)
9 */
10 #include "ossl.h"
11
12 #define NewX509Attr(klass) \
13 TypedData_Wrap_Struct((klass), &ossl_x509attr_type, 0)
14 #define SetX509Attr(obj, attr) do { \
15 if (!(attr)) { \
16 ossl_raise(rb_eRuntimeError, "ATTR wasn't initialized!"); \
17 } \
18 RTYPEDDATA_DATA(obj) = (attr); \
19 } while (0)
20 #define GetX509Attr(obj, attr) do { \
21 TypedData_Get_Struct((obj), X509_ATTRIBUTE, &ossl_x509attr_type, (attr)); \
22 if (!(attr)) { \
23 ossl_raise(rb_eRuntimeError, "ATTR wasn't initialized!"); \
24 } \
25 } while (0)
26
27 /*
28 * Classes
29 */
30 VALUE cX509Attr;
31 VALUE eX509AttrError;
32
33 static void
34 ossl_x509attr_free(void *ptr)
35 {
36 X509_ATTRIBUTE_free(ptr);
37 }
38
39 static const rb_data_type_t ossl_x509attr_type = {
40 "OpenSSL/X509/ATTRIBUTE",
41 {
42 0, ossl_x509attr_free,
43 },
44 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
45 };
46
47 /*
48 * Public
49 */
50 VALUE
51 ossl_x509attr_new(X509_ATTRIBUTE *attr)
52 {
53 X509_ATTRIBUTE *new;
54 VALUE obj;
55
56 obj = NewX509Attr(cX509Attr);
57 if (!attr) {
58 new = X509_ATTRIBUTE_new();
59 } else {
60 new = X509_ATTRIBUTE_dup(attr);
61 }
62 if (!new) {
63 ossl_raise(eX509AttrError, NULL);
64 }
65 SetX509Attr(obj, new);
66
67 return obj;
68 }
69
70 X509_ATTRIBUTE *
71 GetX509AttrPtr(VALUE obj)
72 {
73 X509_ATTRIBUTE *attr;
74
75 GetX509Attr(obj, attr);
76
77 return attr;
78 }
79
80 /*
81 * Private
82 */
83 static VALUE
84 ossl_x509attr_alloc(VALUE klass)
85 {
86 X509_ATTRIBUTE *attr;
87 VALUE obj;
88
89 obj = NewX509Attr(klass);
90 if (!(attr = X509_ATTRIBUTE_new()))
91 ossl_raise(eX509AttrError, NULL);
92 SetX509Attr(obj, attr);
93
94 return obj;
95 }
96
97 /*
98 * call-seq:
99 * Attribute.new(oid [, value]) => attr
100 */
101 static VALUE
102 ossl_x509attr_initialize(int argc, VALUE *argv, VALUE self)
103 {
104 VALUE oid, value;
105 X509_ATTRIBUTE *attr, *x;
106 const unsigned char *p;
107
108 GetX509Attr(self, attr);
109 if(rb_scan_args(argc, argv, "11", &oid, &value) == 1){
110 oid = ossl_to_der_if_possible(oid);
111 StringValue(oid);
112 p = (unsigned char *)RSTRING_PTR(oid);
113 x = d2i_X509_ATTRIBUTE(&attr, &p, RSTRING_LEN(oid));
114 DATA_PTR(self) = attr;
115 if(!x){
116 ossl_raise(eX509AttrError, NULL);
117 }
118 return self;
119 }
120 rb_funcall(self, rb_intern("oid="), 1, oid);
121 rb_funcall(self, rb_intern("value="), 1, value);
122
123 return self;
124 }
125
126 static VALUE
127 ossl_x509attr_initialize_copy(VALUE self, VALUE other)
128 {
129 X509_ATTRIBUTE *attr, *attr_other, *attr_new;
130
131 rb_check_frozen(self);
132 GetX509Attr(self, attr);
133 GetX509Attr(other, attr_other);
134
135 attr_new = X509_ATTRIBUTE_dup(attr_other);
136 if (!attr_new)
137 ossl_raise(eX509AttrError, "X509_ATTRIBUTE_dup");
138
139 SetX509Attr(self, attr_new);
140 X509_ATTRIBUTE_free(attr);
141
142 return self;
143 }
144
145 /*
146 * call-seq:
147 * attr.oid = string => string
148 */
149 static VALUE
150 ossl_x509attr_set_oid(VALUE self, VALUE oid)
151 {
152 X509_ATTRIBUTE *attr;
153 ASN1_OBJECT *obj;
154 char *s;
155
156 GetX509Attr(self, attr);
157 s = StringValueCStr(oid);
158 obj = OBJ_txt2obj(s, 0);
159 if(!obj) ossl_raise(eX509AttrError, NULL);
160 if (!X509_ATTRIBUTE_set1_object(attr, obj)) {
161 ASN1_OBJECT_free(obj);
162 ossl_raise(eX509AttrError, "X509_ATTRIBUTE_set1_object");
163 }
164 ASN1_OBJECT_free(obj);
165
166 return oid;
167 }
168
169 /*
170 * call-seq:
171 * attr.oid => string
172 */
173 static VALUE
174 ossl_x509attr_get_oid(VALUE self)
175 {
176 X509_ATTRIBUTE *attr;
177 ASN1_OBJECT *oid;
178 BIO *out;
179 VALUE ret;
180 int nid;
181
182 GetX509Attr(self, attr);
183 oid = X509_ATTRIBUTE_get0_object(attr);
184 if ((nid = OBJ_obj2nid(oid)) != NID_undef)
185 ret = rb_str_new2(OBJ_nid2sn(nid));
186 else{
187 if (!(out = BIO_new(BIO_s_mem())))
188 ossl_raise(eX509AttrError, NULL);
189 i2a_ASN1_OBJECT(out, oid);
190 ret = ossl_membio2str(out);
191 }
192
193 return ret;
194 }
195
196 /*
197 * call-seq:
198 * attr.value = asn1 => asn1
199 */
200 static VALUE
201 ossl_x509attr_set_value(VALUE self, VALUE value)
202 {
203 X509_ATTRIBUTE *attr;
204 VALUE asn1_value;
205 int i, asn1_tag;
206
207 OSSL_Check_Kind(value, cASN1Data);
208 asn1_tag = NUM2INT(rb_attr_get(value, rb_intern("@tag")));
209 asn1_value = rb_attr_get(value, rb_intern("@value"));
210 if (asn1_tag != V_ASN1_SET)
211 ossl_raise(eASN1Error, "argument must be ASN1::Set");
212 if (!RB_TYPE_P(asn1_value, T_ARRAY))
213 ossl_raise(eASN1Error, "ASN1::Set has non-array value");
214
215 GetX509Attr(self, attr);
216 if (X509_ATTRIBUTE_count(attr)) { /* populated, reset first */
217 ASN1_OBJECT *obj = X509_ATTRIBUTE_get0_object(attr);
218 X509_ATTRIBUTE *new_attr = X509_ATTRIBUTE_create_by_OBJ(NULL, obj, 0, NULL, -1);
219 if (!new_attr)
220 ossl_raise(eX509AttrError, NULL);
221 SetX509Attr(self, new_attr);
222 X509_ATTRIBUTE_free(attr);
223 attr = new_attr;
224 }
225
226 for (i = 0; i < RARRAY_LEN(asn1_value); i++) {
227 ASN1_TYPE *a1type = ossl_asn1_get_asn1type(RARRAY_AREF(asn1_value, i));
228 if (!X509_ATTRIBUTE_set1_data(attr, ASN1_TYPE_get(a1type),
229 a1type->value.ptr, -1)) {
230 ASN1_TYPE_free(a1type);
231 ossl_raise(eX509AttrError, NULL);
232 }
233 ASN1_TYPE_free(a1type);
234 }
235
236 return value;
237 }
238
239 /*
240 * call-seq:
241 * attr.value => asn1
242 */
243 static VALUE
244 ossl_x509attr_get_value(VALUE self)
245 {
246 X509_ATTRIBUTE *attr;
247 STACK_OF(ASN1_TYPE) *sk;
248 VALUE str;
249 int i, count, len;
250 unsigned char *p;
251
252 GetX509Attr(self, attr);
253 /* there is no X509_ATTRIBUTE_get0_set() :( */
254 if (!(sk = sk_ASN1_TYPE_new_null()))
255 ossl_raise(eX509AttrError, "sk_new");
256
257 count = X509_ATTRIBUTE_count(attr);
258 for (i = 0; i < count; i++)
259 sk_ASN1_TYPE_push(sk, X509_ATTRIBUTE_get0_type(attr, i));
260
261 if ((len = i2d_ASN1_SET_ANY(sk, NULL)) <= 0) {
262 sk_ASN1_TYPE_free(sk);
263 ossl_raise(eX509AttrError, NULL);
264 }
265 str = rb_str_new(0, len);
266 p = (unsigned char *)RSTRING_PTR(str);
267 if (i2d_ASN1_SET_ANY(sk, &p) <= 0) {
268 sk_ASN1_TYPE_free(sk);
269 ossl_raise(eX509AttrError, NULL);
270 }
271 ossl_str_adjust(str, p);
272 sk_ASN1_TYPE_free(sk);
273
274 return rb_funcall(mASN1, rb_intern("decode"), 1, str);
275 }
276
277 /*
278 * call-seq:
279 * attr.to_der => string
280 */
281 static VALUE
282 ossl_x509attr_to_der(VALUE self)
283 {
284 X509_ATTRIBUTE *attr;
285 VALUE str;
286 int len;
287 unsigned char *p;
288
289 GetX509Attr(self, attr);
290 if((len = i2d_X509_ATTRIBUTE(attr, NULL)) <= 0)
291 ossl_raise(eX509AttrError, NULL);
292 str = rb_str_new(0, len);
293 p = (unsigned char *)RSTRING_PTR(str);
294 if(i2d_X509_ATTRIBUTE(attr, &p) <= 0)
295 ossl_raise(eX509AttrError, NULL);
296 ossl_str_adjust(str, p);
297
298 return str;
299 }
300
301 /*
302 * X509_ATTRIBUTE init
303 */
304 void
305 Init_ossl_x509attr(void)
306 {
307 #if 0
308 mOSSL = rb_define_module("OpenSSL");
309 eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
310 mX509 = rb_define_module_under(mOSSL, "X509");
311 #endif
312
313 eX509AttrError = rb_define_class_under(mX509, "AttributeError", eOSSLError);
314
315 cX509Attr = rb_define_class_under(mX509, "Attribute", rb_cObject);
316 rb_define_alloc_func(cX509Attr, ossl_x509attr_alloc);
317 rb_define_method(cX509Attr, "initialize", ossl_x509attr_initialize, -1);
318 rb_define_method(cX509Attr, "initialize_copy", ossl_x509attr_initialize_copy, 1);
319 rb_define_method(cX509Attr, "oid=", ossl_x509attr_set_oid, 1);
320 rb_define_method(cX509Attr, "oid", ossl_x509attr_get_oid, 0);
321 rb_define_method(cX509Attr, "value=", ossl_x509attr_set_value, 1);
322 rb_define_method(cX509Attr, "value", ossl_x509attr_get_value, 0);
323 rb_define_method(cX509Attr, "to_der", ossl_x509attr_to_der, 0);
324 }
rb_str_new2
#define rb_str_new2
Definition: intern.h:903
rb_define_module_under
VALUE rb_define_module_under(VALUE outer, const char *name)
Definition: class.c:797
rb_scan_args
#define rb_scan_args(argc, argvp, fmt,...)
Definition: rb_mjit_min_header-2.7.0.h:6372
ossl_to_der_if_possible
VALUE ossl_to_der_if_possible(VALUE obj)
Definition: ossl.c:255
RSTRING_PTR
#define RSTRING_PTR(str)
Definition: ruby.h:1009
rb_attr_get
VALUE rb_attr_get(VALUE, ID)
Definition: variable.c:1084
ossl_membio2str
VALUE ossl_membio2str(BIO *bio)
Definition: ossl_bio.c:29
ossl_x509attr_new
VALUE ossl_x509attr_new(X509_ATTRIBUTE *attr)
Definition: ossl_x509attr.c:51
VALUE
unsigned long VALUE
Definition: ruby.h:102
OSSL_Check_Kind
#define OSSL_Check_Kind(obj, klass)
Definition: ossl.h:56
rb_intern
#define rb_intern(str)
RB_TYPE_P
#define RB_TYPE_P(obj, type)
Definition: ruby.h:560
SetX509Attr
#define SetX509Attr(obj, attr)
Definition: ossl_x509attr.c:14
rb_define_module
VALUE rb_define_module(const char *name)
Definition: class.c:772
mX509
VALUE mX509
Definition: ossl_x509.c:12
ossl.h
StringValue
use StringValue() instead")))
rb_define_method
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1551
ptr
struct RIMemo * ptr
Definition: debug.c:74
Init_ossl_x509attr
void Init_ossl_x509attr(void)
Definition: ossl_x509attr.c:305
ossl_str_adjust
#define ossl_str_adjust(str, p)
Definition: ossl.h:86
NULL
#define NULL
Definition: _sdbm.c:101
GetX509Attr
#define GetX509Attr(obj, attr)
Definition: ossl_x509attr.c:20
cASN1Data
VALUE cASN1Data
Definition: ossl_asn1.c:158
obj
const VALUE VALUE obj
Definition: rb_mjit_min_header-2.7.0.h:5742
mOSSL
VALUE mOSSL
Definition: ossl.c:231
DATA_PTR
#define DATA_PTR(dta)
Definition: ruby.h:1175
GetX509AttrPtr
X509_ATTRIBUTE * GetX509AttrPtr(VALUE obj)
Definition: ossl_x509attr.c:71
rb_check_frozen
#define rb_check_frozen(obj)
Definition: intern.h:319
i
uint32_t i
Definition: rb_mjit_min_header-2.7.0.h:5464
ossl_asn1_get_asn1type
ASN1_TYPE * ossl_asn1_get_asn1type(VALUE obj)
Definition: ossl_asn1.c:495
ossl_raise
void ossl_raise(VALUE exc, const char *fmt,...)
Definition: ossl.c:293
RARRAY_AREF
#define RARRAY_AREF(a, i)
Definition: ruby.h:1101
StringValueCStr
#define StringValueCStr(v)
Definition: ruby.h:604
nid
int nid
Definition: openssl_missing.c:28
RARRAY_LEN
#define RARRAY_LEN(a)
Definition: ruby.h:1070
rb_cObject
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:2010
rb_funcall
#define rb_funcall(recv, mid, argc,...)
Definition: rb_mjit_min_header-2.7.0.h:6585
T_ARRAY
#define T_ARRAY
Definition: ruby.h:530
argv
char ** argv
Definition: ruby.c:223
STACK_OF
STACK_OF(X509) *ossl_x509_ary2sk(VALUE)
klass
VALUE klass
Definition: rb_mjit_min_header-2.7.0.h:13254
str
char str[HTML_ESCAPE_MAX_LEN+1]
Definition: escape.c:18
cX509Attr
VALUE cX509Attr
Definition: ossl_x509attr.c:30
RUBY_TYPED_FREE_IMMEDIATELY
#define RUBY_TYPED_FREE_IMMEDIATELY
Definition: ruby.h:1207
eX509AttrError
VALUE eX509AttrError
Definition: ossl_x509attr.c:31
argc
int argc
Definition: ruby.c:222
eASN1Error
VALUE eASN1Error
Definition: ossl_asn1.c:156
rb_data_type_struct
Definition: ruby.h:1148
rb_str_new
#define rb_str_new(str, len)
Definition: rb_mjit_min_header-2.7.0.h:6116
count
int count
Definition: encoding.c:57
len
uint8_t len
Definition: escape.c:17
eOSSLError
VALUE eOSSLError
Definition: ossl.c:236
NewX509Attr
#define NewX509Attr(klass)
Definition: ossl_x509attr.c:12
mASN1
VALUE mASN1
Definition: ossl_asn1.c:155
rb_define_class_under
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:698
NUM2INT
#define NUM2INT(x)
Definition: ruby.h:715
rb_eStandardError
VALUE rb_eStandardError
Definition: error.c:919
RSTRING_LEN
#define RSTRING_LEN(str)
Definition: ruby.h:1005
rb_define_alloc_func
void rb_define_alloc_func(VALUE, rb_alloc_func_t)