Ruby  3.1.0dev(2021-09-10revisionb76ad15ed0da636161de0243c547ee1e6fc95681)
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  */
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  },
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) {
64  }
65  SetX509Attr(obj, new);
66 
67  return obj;
68 }
69 
70 X509_ATTRIBUTE *
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()))
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){
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())))
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)
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);
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);
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);
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)
292  str = rb_str_new(0, len);
293  p = (unsigned char *)RSTRING_PTR(str);
294  if(i2d_X509_ATTRIBUTE(attr, &p) <= 0)
296  ossl_str_adjust(str, p);
297 
298  return str;
299 }
300 
301 /*
302  * X509_ATTRIBUTE init
303  */
304 void
306 {
307 #if 0
308  mOSSL = rb_define_module("OpenSSL");
311 #endif
312 
314 
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 }
StringValue
#define StringValue(v)
Definition: rstring.h:50
rb_define_module_under
VALUE rb_define_module_under(VALUE outer, const char *name)
Definition: class.c:914
rb_intern
ID rb_intern(const char *)
Definition: symbol.c:784
ossl_to_der_if_possible
VALUE ossl_to_der_if_possible(VALUE obj)
Definition: ossl.c:261
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
OSSL_Check_Kind
#define OSSL_Check_Kind(obj, klass)
Definition: ossl.h:58
SetX509Attr
#define SetX509Attr(obj, attr)
Definition: ossl_x509attr.c:14
rb_define_module
VALUE rb_define_module(const char *name)
Definition: class.c:887
mX509
VALUE mX509
Definition: ossl_x509.c:12
ossl.h
argv
char ** argv
Definition: ruby.c:243
ptr
struct RIMemo * ptr
Definition: debug.c:87
Init_ossl_x509attr
void Init_ossl_x509attr(void)
Definition: ossl_x509attr.c:305
NUM2INT
#define NUM2INT
Definition: int.h:44
ossl_str_adjust
#define ossl_str_adjust(str, p)
Definition: ossl.h:88
RSTRING_LEN
#define RSTRING_LEN(string)
Definition: fbuffer.h:22
rb_str_new
#define rb_str_new(str, len)
Definition: string.h:213
GetX509Attr
#define GetX509Attr(obj, attr)
Definition: ossl_x509attr.c:20
RUBY_TYPED_FREE_IMMEDIATELY
@ RUBY_TYPED_FREE_IMMEDIATELY
Definition: rtypeddata.h:62
cASN1Data
VALUE cASN1Data
Definition: ossl_asn1.c:158
mOSSL
VALUE mOSSL
Definition: ossl.c:237
GetX509AttrPtr
X509_ATTRIBUTE * GetX509AttrPtr(VALUE obj)
Definition: ossl_x509attr.c:71
rb_define_alloc_func
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
rb_cObject
VALUE rb_cObject
Object class.
Definition: object.c:50
ossl_asn1_get_asn1type
ASN1_TYPE * ossl_asn1_get_asn1type(VALUE obj)
Definition: ossl_asn1.c:495
len
uint8_t len
Definition: escape.c:17
ossl_raise
void ossl_raise(VALUE exc, const char *fmt,...)
Definition: ossl.c:299
NULL
#define NULL
Definition: regenc.h:69
rb_scan_args
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:2347
rb_attr_get
VALUE rb_attr_get(VALUE, ID)
Definition: variable.c:1245
VALUE
unsigned long VALUE
Definition: value.h:38
rb_funcall
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
Definition: vm_eval.c:1113
STACK_OF
STACK_OF(X509) *ossl_x509_ary2sk(VALUE)
RSTRING_PTR
#define RSTRING_PTR(string)
Definition: fbuffer.h:19
str
char str[HTML_ESCAPE_MAX_LEN+1]
Definition: escape.c:18
cX509Attr
VALUE cX509Attr
Definition: ossl_x509attr.c:30
ret
return ret
Definition: memory.h:232
eX509AttrError
VALUE eX509AttrError
Definition: ossl_x509attr.c:31
rb_check_frozen
#define rb_check_frozen
Definition: error.h:72
argc
int argc
Definition: ruby.c:242
rb_str_new2
#define rb_str_new2
Definition: string.h:276
eASN1Error
VALUE eASN1Error
Definition: ossl_asn1.c:156
T_ARRAY
#define T_ARRAY
Definition: value_type.h:56
rb_data_type_struct
Definition: rtypeddata.h:70
RARRAY_AREF
#define RARRAY_AREF(a, i)
Definition: missing.h:201
count
int count
Definition: nkf.c:5055
eOSSLError
VALUE eOSSLError
Definition: ossl.c:242
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:809
DATA_PTR
#define DATA_PTR(obj)
Definition: rdata.h:55
StringValueCStr
#define StringValueCStr(v)
Definition: rstring.h:52
rb_define_method
#define rb_define_method(klass, mid, func, arity)
Defines klass#mid.
Definition: cxxanyargs.hpp:655
RARRAY_LEN
#define RARRAY_LEN
Definition: rarray.h:52
rb_eStandardError
VALUE rb_eStandardError
Definition: error.c:1090