Ruby  2.5.0dev(2017-10-22revision60238)
ossl_x509ext.c
Go to the documentation of this file.
1 /*
2  * 'OpenSSL for Ruby' project
3  * Copyright (C) 2001-2002 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 NewX509Ext(klass) \
13  TypedData_Wrap_Struct((klass), &ossl_x509ext_type, 0)
14 #define SetX509Ext(obj, ext) do { \
15  if (!(ext)) { \
16  ossl_raise(rb_eRuntimeError, "EXT wasn't initialized!"); \
17  } \
18  RTYPEDDATA_DATA(obj) = (ext); \
19 } while (0)
20 #define GetX509Ext(obj, ext) do { \
21  TypedData_Get_Struct((obj), X509_EXTENSION, &ossl_x509ext_type, (ext)); \
22  if (!(ext)) { \
23  ossl_raise(rb_eRuntimeError, "EXT wasn't initialized!"); \
24  } \
25 } while (0)
26 #define MakeX509ExtFactory(klass, obj, ctx) do { \
27  (obj) = TypedData_Wrap_Struct((klass), &ossl_x509extfactory_type, 0); \
28  if (!((ctx) = OPENSSL_malloc(sizeof(X509V3_CTX)))) \
29  ossl_raise(rb_eRuntimeError, "CTX wasn't allocated!"); \
30  X509V3_set_ctx((ctx), NULL, NULL, NULL, NULL, 0); \
31  RTYPEDDATA_DATA(obj) = (ctx); \
32 } while (0)
33 #define GetX509ExtFactory(obj, ctx) do { \
34  TypedData_Get_Struct((obj), X509V3_CTX, &ossl_x509extfactory_type, (ctx)); \
35  if (!(ctx)) { \
36  ossl_raise(rb_eRuntimeError, "CTX wasn't initialized!"); \
37  } \
38 } while (0)
39 
40 /*
41  * Classes
42  */
46 
47 static void
48 ossl_x509ext_free(void *ptr)
49 {
50  X509_EXTENSION_free(ptr);
51 }
52 
53 static const rb_data_type_t ossl_x509ext_type = {
54  "OpenSSL/X509/EXTENSION",
55  {
56  0, ossl_x509ext_free,
57  },
59 };
60 
61 /*
62  * Public
63  */
64 VALUE
65 ossl_x509ext_new(X509_EXTENSION *ext)
66 {
67  X509_EXTENSION *new;
68  VALUE obj;
69 
70  obj = NewX509Ext(cX509Ext);
71  if (!ext) {
72  new = X509_EXTENSION_new();
73  } else {
74  new = X509_EXTENSION_dup(ext);
75  }
76  if (!new) {
78  }
79  SetX509Ext(obj, new);
80 
81  return obj;
82 }
83 
84 X509_EXTENSION *
86 {
87  X509_EXTENSION *ext;
88 
89  GetX509Ext(obj, ext);
90 
91  return ext;
92 }
93 
94 /*
95  * Private
96  */
97 /*
98  * Ext factory
99  */
100 static void
101 ossl_x509extfactory_free(void *ctx)
102 {
103  OPENSSL_free(ctx);
104 }
105 
106 static const rb_data_type_t ossl_x509extfactory_type = {
107  "OpenSSL/X509/EXTENSION/Factory",
108  {
109  0, ossl_x509extfactory_free,
110  },
112 };
113 
114 static VALUE
115 ossl_x509extfactory_alloc(VALUE klass)
116 {
117  X509V3_CTX *ctx;
118  VALUE obj;
119 
120  MakeX509ExtFactory(klass, obj, ctx);
121  rb_iv_set(obj, "@config", Qnil);
122 
123  return obj;
124 }
125 
126 static VALUE
127 ossl_x509extfactory_set_issuer_cert(VALUE self, VALUE cert)
128 {
129  X509V3_CTX *ctx;
130 
131  GetX509ExtFactory(self, ctx);
132  rb_iv_set(self, "@issuer_certificate", cert);
133  ctx->issuer_cert = GetX509CertPtr(cert); /* NO DUP NEEDED */
134 
135  return cert;
136 }
137 
138 static VALUE
139 ossl_x509extfactory_set_subject_cert(VALUE self, VALUE cert)
140 {
141  X509V3_CTX *ctx;
142 
143  GetX509ExtFactory(self, ctx);
144  rb_iv_set(self, "@subject_certificate", cert);
145  ctx->subject_cert = GetX509CertPtr(cert); /* NO DUP NEEDED */
146 
147  return cert;
148 }
149 
150 static VALUE
151 ossl_x509extfactory_set_subject_req(VALUE self, VALUE req)
152 {
153  X509V3_CTX *ctx;
154 
155  GetX509ExtFactory(self, ctx);
156  rb_iv_set(self, "@subject_request", req);
157  ctx->subject_req = GetX509ReqPtr(req); /* NO DUP NEEDED */
158 
159  return req;
160 }
161 
162 static VALUE
163 ossl_x509extfactory_set_crl(VALUE self, VALUE crl)
164 {
165  X509V3_CTX *ctx;
166 
167  GetX509ExtFactory(self, ctx);
168  rb_iv_set(self, "@crl", crl);
169  ctx->crl = GetX509CRLPtr(crl); /* NO DUP NEEDED */
170 
171  return crl;
172 }
173 
174 static VALUE
175 ossl_x509extfactory_initialize(int argc, VALUE *argv, VALUE self)
176 {
177  /*X509V3_CTX *ctx;*/
178  VALUE issuer_cert, subject_cert, subject_req, crl;
179 
180  /*GetX509ExtFactory(self, ctx);*/
181 
182  rb_scan_args(argc, argv, "04",
183  &issuer_cert, &subject_cert, &subject_req, &crl);
184  if (!NIL_P(issuer_cert))
185  ossl_x509extfactory_set_issuer_cert(self, issuer_cert);
186  if (!NIL_P(subject_cert))
187  ossl_x509extfactory_set_subject_cert(self, subject_cert);
188  if (!NIL_P(subject_req))
189  ossl_x509extfactory_set_subject_req(self, subject_req);
190  if (!NIL_P(crl))
191  ossl_x509extfactory_set_crl(self, crl);
192 
193  return self;
194 }
195 
196 /*
197  * call-seq:
198  * ef.create_ext(ln_or_sn, "value", critical = false) -> X509::Extension
199  * ef.create_ext(ln_or_sn, "critical,value") -> X509::Extension
200  *
201  * Creates a new X509::Extension with passed values. See also x509v3_config(5).
202  */
203 static VALUE
204 ossl_x509extfactory_create_ext(int argc, VALUE *argv, VALUE self)
205 {
206  X509V3_CTX *ctx;
207  X509_EXTENSION *ext;
208  VALUE oid, value, critical, valstr, obj;
209  int nid;
210  VALUE rconf;
211  CONF *conf;
212 
213  rb_scan_args(argc, argv, "21", &oid, &value, &critical);
214  StringValueCStr(oid);
215  StringValue(value);
216  if(NIL_P(critical)) critical = Qfalse;
217 
218  nid = OBJ_ln2nid(RSTRING_PTR(oid));
219  if(!nid) nid = OBJ_sn2nid(RSTRING_PTR(oid));
220  if(!nid) ossl_raise(eX509ExtError, "unknown OID `%"PRIsVALUE"'", oid);
221 
222  valstr = rb_str_new2(RTEST(critical) ? "critical," : "");
223  rb_str_append(valstr, value);
224  StringValueCStr(valstr);
225 
226  GetX509ExtFactory(self, ctx);
227  obj = NewX509Ext(cX509Ext);
228  rconf = rb_iv_get(self, "@config");
229  conf = NIL_P(rconf) ? NULL : DupConfigPtr(rconf);
230  X509V3_set_nconf(ctx, conf);
231  ext = X509V3_EXT_nconf_nid(conf, ctx, nid, RSTRING_PTR(valstr));
232  X509V3_set_ctx_nodb(ctx);
233  NCONF_free(conf);
234  if (!ext){
235  ossl_raise(eX509ExtError, "%"PRIsVALUE" = %"PRIsVALUE, oid, valstr);
236  }
237  SetX509Ext(obj, ext);
238 
239  return obj;
240 }
241 
242 /*
243  * Ext
244  */
245 static VALUE
246 ossl_x509ext_alloc(VALUE klass)
247 {
248  X509_EXTENSION *ext;
249  VALUE obj;
250 
251  obj = NewX509Ext(klass);
252  if(!(ext = X509_EXTENSION_new())){
254  }
255  SetX509Ext(obj, ext);
256 
257  return obj;
258 }
259 
260 /*
261  * call-seq:
262  * OpenSSL::X509::Extension.new(der)
263  * OpenSSL::X509::Extension.new(oid, value)
264  * OpenSSL::X509::Extension.new(oid, value, critical)
265  *
266  * Creates an X509 extension.
267  *
268  * The extension may be created from _der_ data or from an extension _oid_
269  * and _value_. The _oid_ may be either an OID or an extension name. If
270  * _critical_ is +true+ the extension is marked critical.
271  */
272 static VALUE
273 ossl_x509ext_initialize(int argc, VALUE *argv, VALUE self)
274 {
275  VALUE oid, value, critical;
276  const unsigned char *p;
277  X509_EXTENSION *ext, *x;
278 
279  GetX509Ext(self, ext);
280  if(rb_scan_args(argc, argv, "12", &oid, &value, &critical) == 1){
281  oid = ossl_to_der_if_possible(oid);
282  StringValue(oid);
283  p = (unsigned char *)RSTRING_PTR(oid);
284  x = d2i_X509_EXTENSION(&ext, &p, RSTRING_LEN(oid));
285  DATA_PTR(self) = ext;
286  if(!x)
288  return self;
289  }
290  rb_funcall(self, rb_intern("oid="), 1, oid);
291  rb_funcall(self, rb_intern("value="), 1, value);
292  if(argc > 2) rb_funcall(self, rb_intern("critical="), 1, critical);
293 
294  return self;
295 }
296 
297 static VALUE
298 ossl_x509ext_initialize_copy(VALUE self, VALUE other)
299 {
300  X509_EXTENSION *ext, *ext_other, *ext_new;
301 
302  rb_check_frozen(self);
303  GetX509Ext(self, ext);
304  GetX509Ext(other, ext_other);
305 
306  ext_new = X509_EXTENSION_dup(ext_other);
307  if (!ext_new)
308  ossl_raise(eX509ExtError, "X509_EXTENSION_dup");
309 
310  SetX509Ext(self, ext_new);
311  X509_EXTENSION_free(ext);
312 
313  return self;
314 }
315 
316 static VALUE
317 ossl_x509ext_set_oid(VALUE self, VALUE oid)
318 {
319  X509_EXTENSION *ext;
320  ASN1_OBJECT *obj;
321 
322  GetX509Ext(self, ext);
323  obj = OBJ_txt2obj(StringValueCStr(oid), 0);
324  if (!obj)
325  ossl_raise(eX509ExtError, "OBJ_txt2obj");
326  if (!X509_EXTENSION_set_object(ext, obj)) {
327  ASN1_OBJECT_free(obj);
328  ossl_raise(eX509ExtError, "X509_EXTENSION_set_object");
329  }
330  ASN1_OBJECT_free(obj);
331 
332  return oid;
333 }
334 
335 static VALUE
336 ossl_x509ext_set_value(VALUE self, VALUE data)
337 {
338  X509_EXTENSION *ext;
339  ASN1_OCTET_STRING *asn1s;
340 
341  GetX509Ext(self, ext);
342  data = ossl_to_der_if_possible(data);
343  StringValue(data);
344  asn1s = X509_EXTENSION_get_data(ext);
345 
346  if (!ASN1_OCTET_STRING_set(asn1s, (unsigned char *)RSTRING_PTR(data),
347  RSTRING_LENINT(data))) {
348  ossl_raise(eX509ExtError, "ASN1_OCTET_STRING_set");
349  }
350 
351  return data;
352 }
353 
354 static VALUE
355 ossl_x509ext_set_critical(VALUE self, VALUE flag)
356 {
357  X509_EXTENSION *ext;
358 
359  GetX509Ext(self, ext);
360  X509_EXTENSION_set_critical(ext, RTEST(flag) ? 1 : 0);
361 
362  return flag;
363 }
364 
365 static VALUE
366 ossl_x509ext_get_oid(VALUE obj)
367 {
368  X509_EXTENSION *ext;
369  ASN1_OBJECT *extobj;
370  BIO *out;
371  VALUE ret;
372  int nid;
373 
374  GetX509Ext(obj, ext);
375  extobj = X509_EXTENSION_get_object(ext);
376  if ((nid = OBJ_obj2nid(extobj)) != NID_undef)
377  ret = rb_str_new2(OBJ_nid2sn(nid));
378  else{
379  if (!(out = BIO_new(BIO_s_mem())))
381  i2a_ASN1_OBJECT(out, extobj);
382  ret = ossl_membio2str(out);
383  }
384 
385  return ret;
386 }
387 
388 static VALUE
389 ossl_x509ext_get_value(VALUE obj)
390 {
391  X509_EXTENSION *ext;
392  BIO *out;
393  VALUE ret;
394 
395  GetX509Ext(obj, ext);
396  if (!(out = BIO_new(BIO_s_mem())))
398  if (!X509V3_EXT_print(out, ext, 0, 0))
399  ASN1_STRING_print(out, (ASN1_STRING *)X509_EXTENSION_get_data(ext));
400  ret = ossl_membio2str(out);
401 
402  return ret;
403 }
404 
405 static VALUE
406 ossl_x509ext_get_critical(VALUE obj)
407 {
408  X509_EXTENSION *ext;
409 
410  GetX509Ext(obj, ext);
411  return X509_EXTENSION_get_critical(ext) ? Qtrue : Qfalse;
412 }
413 
414 static VALUE
415 ossl_x509ext_to_der(VALUE obj)
416 {
417  X509_EXTENSION *ext;
418  unsigned char *p;
419  long len;
420  VALUE str;
421 
422  GetX509Ext(obj, ext);
423  if((len = i2d_X509_EXTENSION(ext, NULL)) <= 0)
425  str = rb_str_new(0, len);
426  p = (unsigned char *)RSTRING_PTR(str);
427  if(i2d_X509_EXTENSION(ext, &p) < 0)
429  ossl_str_adjust(str, p);
430 
431  return str;
432 }
433 
434 /*
435  * INIT
436  */
437 void
439 {
440 #if 0
441  mOSSL = rb_define_module("OpenSSL");
444 #endif
445 
446  eX509ExtError = rb_define_class_under(mX509, "ExtensionError", eOSSLError);
447 
448  cX509ExtFactory = rb_define_class_under(mX509, "ExtensionFactory", rb_cObject);
449 
450  rb_define_alloc_func(cX509ExtFactory, ossl_x509extfactory_alloc);
451  rb_define_method(cX509ExtFactory, "initialize", ossl_x509extfactory_initialize, -1);
452 
453  rb_attr(cX509ExtFactory, rb_intern("issuer_certificate"), 1, 0, Qfalse);
454  rb_attr(cX509ExtFactory, rb_intern("subject_certificate"), 1, 0, Qfalse);
455  rb_attr(cX509ExtFactory, rb_intern("subject_request"), 1, 0, Qfalse);
456  rb_attr(cX509ExtFactory, rb_intern("crl"), 1, 0, Qfalse);
457  rb_attr(cX509ExtFactory, rb_intern("config"), 1, 1, Qfalse);
458 
459  rb_define_method(cX509ExtFactory, "issuer_certificate=", ossl_x509extfactory_set_issuer_cert, 1);
460  rb_define_method(cX509ExtFactory, "subject_certificate=", ossl_x509extfactory_set_subject_cert, 1);
461  rb_define_method(cX509ExtFactory, "subject_request=", ossl_x509extfactory_set_subject_req, 1);
462  rb_define_method(cX509ExtFactory, "crl=", ossl_x509extfactory_set_crl, 1);
463  rb_define_method(cX509ExtFactory, "create_ext", ossl_x509extfactory_create_ext, -1);
464 
466  rb_define_alloc_func(cX509Ext, ossl_x509ext_alloc);
467  rb_define_method(cX509Ext, "initialize", ossl_x509ext_initialize, -1);
468  rb_define_method(cX509Ext, "initialize_copy", ossl_x509ext_initialize_copy, 1);
469  rb_define_method(cX509Ext, "oid=", ossl_x509ext_set_oid, 1);
470  rb_define_method(cX509Ext, "value=", ossl_x509ext_set_value, 1);
471  rb_define_method(cX509Ext, "critical=", ossl_x509ext_set_critical, 1);
472  rb_define_method(cX509Ext, "oid", ossl_x509ext_get_oid, 0);
473  rb_define_method(cX509Ext, "value", ossl_x509ext_get_value, 0);
474  rb_define_method(cX509Ext, "critical?", ossl_x509ext_get_critical, 0);
475  rb_define_method(cX509Ext, "to_der", ossl_x509ext_to_der, 0);
476 }
VALUE mOSSL
Definition: ossl.c:231
#define RUBY_TYPED_FREE_IMMEDIATELY
Definition: ruby.h:1138
#define Qtrue
Definition: ruby.h:437
#define ossl_str_adjust(str, p)
Definition: ossl.h:82
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
Definition: vm_eval.c:774
VALUE rb_iv_set(VALUE, const char *, VALUE)
Definition: variable.c:3095
VALUE rb_iv_get(VALUE, const char *)
Definition: variable.c:3087
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:693
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
#define DATA_PTR(dta)
Definition: ruby.h:1106
VALUE ossl_membio2str(BIO *bio)
Definition: ossl_bio.c:29
VALUE cX509Ext
Definition: ossl_x509ext.c:43
#define NewX509Ext(klass)
Definition: ossl_x509ext.c:12
#define GetX509ExtFactory(obj, ctx)
Definition: ossl_x509ext.c:33
X509 * GetX509CertPtr(VALUE)
Definition: ossl_x509cert.c:71
void Init_ossl_x509ext(void)
Definition: ossl_x509ext.c:438
VALUE ossl_to_der_if_possible(VALUE obj)
Definition: ossl.c:255
X509_EXTENSION * GetX509ExtPtr(VALUE obj)
Definition: ossl_x509ext.c:85
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:1893
void rb_attr(VALUE, ID, int, int, int)
Definition: vm_method.c:1137
#define NIL_P(v)
Definition: ruby.h:451
VALUE ossl_x509ext_new(X509_EXTENSION *ext)
Definition: ossl_x509ext.c:65
VALUE eOSSLError
Definition: ossl.c:236
int argc
Definition: ruby.c:187
#define Qfalse
Definition: ruby.h:436
#define SetX509Ext(obj, ext)
Definition: ossl_x509ext.c:14
#define rb_str_new2
Definition: intern.h:835
VALUE cX509ExtFactory
Definition: ossl_x509ext.c:44
#define RSTRING_LEN(str)
Definition: ruby.h:971
CONF * DupConfigPtr(VALUE obj)
Definition: ossl_config.c:35
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1908
#define PRIsVALUE
Definition: ruby.h:135
#define Qnil
Definition: ruby.h:438
VALUE rb_eStandardError
Definition: error.c:799
unsigned long VALUE
Definition: ruby.h:85
VALUE mX509
Definition: ossl_x509.c:12
VALUE eX509ExtError
Definition: ossl_x509ext.c:45
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 MakeX509ExtFactory(klass, obj, ctx)
Definition: ossl_x509ext.c:26
#define RTEST(v)
Definition: ruby.h:450
void ossl_raise(VALUE exc, const char *fmt,...)
Definition: ossl.c:293
int nid
#define RSTRING_LENINT(str)
Definition: ruby.h:983
#define rb_check_frozen(obj)
Definition: intern.h:271
VALUE rb_define_module(const char *name)
Definition: class.c:768
X509_CRL * GetX509CRLPtr(VALUE)
Definition: ossl_x509crl.c:51
#define rb_intern(str)
#define NULL
Definition: _sdbm.c:102
X509_REQ * GetX509ReqPtr(VALUE)
Definition: ossl_x509req.c:51
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1515
VALUE rb_str_append(VALUE, VALUE)
Definition: string.c:2900
#define GetX509Ext(obj, ext)
Definition: ossl_x509ext.c:20
char ** argv
Definition: ruby.c:188
#define StringValue(v)
Definition: ruby.h:569
VALUE rb_str_new(const char *, long)
Definition: string.c:737