Ruby  2.5.0dev(2017-10-22revision60238)
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 }
VALUE mOSSL
Definition: ossl.c:231
VALUE cASN1Data
Definition: ossl_asn1.c:158
#define RARRAY_LEN(a)
Definition: ruby.h:1019
#define RUBY_TYPED_FREE_IMMEDIATELY
Definition: ruby.h:1138
#define NUM2INT(x)
Definition: ruby.h:684
int count
Definition: encoding.c:56
void Init_ossl_x509attr(void)
#define NewX509Attr(klass)
Definition: ossl_x509attr.c:12
#define ossl_str_adjust(str, p)
Definition: ossl.h:82
VALUE mASN1
Definition: ossl_asn1.c:155
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
Definition: vm_eval.c:774
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:693
VALUE eX509AttrError
Definition: ossl_x509attr.c:31
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
#define DATA_PTR(dta)
Definition: ruby.h:1106
#define T_ARRAY
Definition: ruby.h:498
VALUE ossl_membio2str(BIO *bio)
Definition: ossl_bio.c:29
#define RB_TYPE_P(obj, type)
Definition: ruby.h:527
VALUE ossl_to_der_if_possible(VALUE obj)
Definition: ossl.c:255
VALUE ossl_x509attr_new(X509_ATTRIBUTE *attr)
Definition: ossl_x509attr.c:51
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:1893
STACK_OF(X509) *ossl_x509_ary2sk(VALUE)
#define SetX509Attr(obj, attr)
Definition: ossl_x509attr.c:14
VALUE eOSSLError
Definition: ossl.c:236
X509_ATTRIBUTE * GetX509AttrPtr(VALUE obj)
Definition: ossl_x509attr.c:71
int argc
Definition: ruby.c:187
#define rb_str_new2
Definition: intern.h:835
ASN1_TYPE * ossl_asn1_get_asn1type(VALUE obj)
Definition: ossl_asn1.c:495
#define RSTRING_LEN(str)
Definition: ruby.h:971
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1908
VALUE rb_eStandardError
Definition: error.c:799
unsigned long VALUE
Definition: ruby.h:85
VALUE cX509Attr
Definition: ossl_x509attr.c:30
VALUE mX509
Definition: ossl_x509.c:12
register unsigned int len
Definition: zonetab.h:51
VALUE rb_define_module_under(VALUE outer, const char *name)
Definition: class.c:790
#define StringValueCStr(v)
Definition: ruby.h:571
#define RSTRING_PTR(str)
Definition: ruby.h:975
#define RARRAY_AREF(a, i)
Definition: ruby.h:1033
#define OSSL_Check_Kind(obj, klass)
Definition: ossl.h:52
void ossl_raise(VALUE exc, const char *fmt,...)
Definition: ossl.c:293
int nid
#define rb_check_frozen(obj)
Definition: intern.h:271
VALUE rb_define_module(const char *name)
Definition: class.c:768
#define rb_intern(str)
#define NULL
Definition: _sdbm.c:102
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1515
VALUE eASN1Error
Definition: ossl_asn1.c:156
VALUE rb_attr_get(VALUE, ID)
Definition: variable.c:1224
char ** argv
Definition: ruby.c:188
#define StringValue(v)
Definition: ruby.h:569
VALUE rb_str_new(const char *, long)
Definition: string.c:737
#define GetX509Attr(obj, attr)
Definition: ossl_x509attr.c:20