Ruby 2.7.0p0(2019-12-25revision647ee6f091eafcce70ffb75ddf7e121e192ab217)

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 */
43 VALUE cX509Ext;
44 VALUE cX509ExtFactory;
45 VALUE eX509ExtError;
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 },
58 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
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) {
77 ossl_raise(eX509ExtError, NULL);
78 }
79 SetX509Ext(obj, new);
80
81 return obj;
82 }
83
84 X509_EXTENSION *
85 GetX509ExtPtr(VALUE obj)
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 },
111 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
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())){
253 ossl_raise(eX509ExtError, NULL);
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)
287 ossl_raise(eX509ExtError, NULL);
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())))
380 ossl_raise(eX509ExtError, NULL);
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())))
397 ossl_raise(eX509ExtError, NULL);
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)
424 ossl_raise(eX509ExtError, NULL);
425 str = rb_str_new(0, len);
426 p = (unsigned char *)RSTRING_PTR(str);
427 if(i2d_X509_EXTENSION(ext, &p) < 0)
428 ossl_raise(eX509ExtError, NULL);
429 ossl_str_adjust(str, p);
430
431 return str;
432 }
433
434 /*
435 * INIT
436 */
437 void
438 Init_ossl_x509ext(void)
439 {
440 #undef rb_intern
441 #if 0
442 mOSSL = rb_define_module("OpenSSL");
443 eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
444 mX509 = rb_define_module_under(mOSSL, "X509");
445 #endif
446
447 eX509ExtError = rb_define_class_under(mX509, "ExtensionError", eOSSLError);
448
449 cX509ExtFactory = rb_define_class_under(mX509, "ExtensionFactory", rb_cObject);
450
451 rb_define_alloc_func(cX509ExtFactory, ossl_x509extfactory_alloc);
452 rb_define_method(cX509ExtFactory, "initialize", ossl_x509extfactory_initialize, -1);
453
454 rb_attr(cX509ExtFactory, rb_intern("issuer_certificate"), 1, 0, Qfalse);
455 rb_attr(cX509ExtFactory, rb_intern("subject_certificate"), 1, 0, Qfalse);
456 rb_attr(cX509ExtFactory, rb_intern("subject_request"), 1, 0, Qfalse);
457 rb_attr(cX509ExtFactory, rb_intern("crl"), 1, 0, Qfalse);
458 rb_attr(cX509ExtFactory, rb_intern("config"), 1, 1, Qfalse);
459
460 rb_define_method(cX509ExtFactory, "issuer_certificate=", ossl_x509extfactory_set_issuer_cert, 1);
461 rb_define_method(cX509ExtFactory, "subject_certificate=", ossl_x509extfactory_set_subject_cert, 1);
462 rb_define_method(cX509ExtFactory, "subject_request=", ossl_x509extfactory_set_subject_req, 1);
463 rb_define_method(cX509ExtFactory, "crl=", ossl_x509extfactory_set_crl, 1);
464 rb_define_method(cX509ExtFactory, "create_ext", ossl_x509extfactory_create_ext, -1);
465
466 cX509Ext = rb_define_class_under(mX509, "Extension", rb_cObject);
467 rb_define_alloc_func(cX509Ext, ossl_x509ext_alloc);
468 rb_define_method(cX509Ext, "initialize", ossl_x509ext_initialize, -1);
469 rb_define_method(cX509Ext, "initialize_copy", ossl_x509ext_initialize_copy, 1);
470 rb_define_method(cX509Ext, "oid=", ossl_x509ext_set_oid, 1);
471 rb_define_method(cX509Ext, "value=", ossl_x509ext_set_value, 1);
472 rb_define_method(cX509Ext, "critical=", ossl_x509ext_set_critical, 1);
473 rb_define_method(cX509Ext, "oid", ossl_x509ext_get_oid, 0);
474 rb_define_method(cX509Ext, "value", ossl_x509ext_get_value, 0);
475 rb_define_method(cX509Ext, "critical?", ossl_x509ext_get_critical, 0);
476 rb_define_method(cX509Ext, "to_der", ossl_x509ext_to_der, 0);
477 }
DupConfigPtr
CONF * DupConfigPtr(VALUE obj)
Definition: ossl_config.c:35
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
ossl_membio2str
VALUE ossl_membio2str(BIO *bio)
Definition: ossl_bio.c:29
VALUE
unsigned long VALUE
Definition: ruby.h:102
rb_intern
#define rb_intern(str)
RSTRING_LENINT
#define RSTRING_LENINT(str)
Definition: ruby.h:1017
rb_define_module
VALUE rb_define_module(const char *name)
Definition: class.c:772
mX509
VALUE mX509
Definition: ossl_x509.c:12
ossl.h
cX509Ext
VALUE cX509Ext
Definition: ossl_x509ext.c:43
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
GetX509ExtFactory
#define GetX509ExtFactory(obj, ctx)
Definition: ossl_x509ext.c:33
ptr
struct RIMemo * ptr
Definition: debug.c:74
Qfalse
#define Qfalse
Definition: ruby.h:467
ossl_str_adjust
#define ossl_str_adjust(str, p)
Definition: ossl.h:86
NULL
#define NULL
Definition: _sdbm.c:101
PRIsVALUE
#define PRIsVALUE
Definition: ruby.h:166
cX509ExtFactory
VALUE cX509ExtFactory
Definition: ossl_x509ext.c:44
GetX509ExtPtr
X509_EXTENSION * GetX509ExtPtr(VALUE obj)
Definition: ossl_x509ext.c:85
obj
const VALUE VALUE obj
Definition: rb_mjit_min_header-2.7.0.h:5742
Init_ossl_x509ext
void Init_ossl_x509ext(void)
Definition: ossl_x509ext.c:438
mOSSL
VALUE mOSSL
Definition: ossl.c:231
DATA_PTR
#define DATA_PTR(dta)
Definition: ruby.h:1175
rb_check_frozen
#define rb_check_frozen(obj)
Definition: intern.h:319
GetX509CRLPtr
X509_CRL * GetX509CRLPtr(VALUE)
Definition: ossl_x509crl.c:51
GetX509CertPtr
X509 * GetX509CertPtr(VALUE)
Definition: ossl_x509cert.c:71
rb_iv_get
VALUE rb_iv_get(VALUE, const char *)
Definition: variable.c:3294
NewX509Ext
#define NewX509Ext(klass)
Definition: ossl_x509ext.c:12
ossl_raise
void ossl_raise(VALUE exc, const char *fmt,...)
Definition: ossl.c:293
ossl_x509ext_new
VALUE ossl_x509ext_new(X509_EXTENSION *ext)
Definition: ossl_x509ext.c:65
StringValueCStr
#define StringValueCStr(v)
Definition: ruby.h:604
SetX509Ext
#define SetX509Ext(obj, ext)
Definition: ossl_x509ext.c:14
nid
int nid
Definition: openssl_missing.c:28
rb_cObject
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:2010
MakeX509ExtFactory
#define MakeX509ExtFactory(klass, obj, ctx)
Definition: ossl_x509ext.c:26
rb_funcall
#define rb_funcall(recv, mid, argc,...)
Definition: rb_mjit_min_header-2.7.0.h:6585
rb_str_append
VALUE rb_str_append(VALUE, VALUE)
Definition: string.c:2965
argv
char ** argv
Definition: ruby.c:223
klass
VALUE klass
Definition: rb_mjit_min_header-2.7.0.h:13254
eX509ExtError
VALUE eX509ExtError
Definition: ossl_x509ext.c:45
str
char str[HTML_ESCAPE_MAX_LEN+1]
Definition: escape.c:18
RUBY_TYPED_FREE_IMMEDIATELY
#define RUBY_TYPED_FREE_IMMEDIATELY
Definition: ruby.h:1207
NIL_P
#define NIL_P(v)
Definition: ruby.h:482
argc
int argc
Definition: ruby.c:222
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
Qtrue
#define Qtrue
Definition: ruby.h:468
len
uint8_t len
Definition: escape.c:17
GetX509Ext
#define GetX509Ext(obj, ext)
Definition: ossl_x509ext.c:20
GetX509ReqPtr
X509_REQ * GetX509ReqPtr(VALUE)
Definition: ossl_x509req.c:51
eOSSLError
VALUE eOSSLError
Definition: ossl.c:236
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
Qnil
#define Qnil
Definition: ruby.h:469
rb_eStandardError
VALUE rb_eStandardError
Definition: error.c:919
RSTRING_LEN
#define RSTRING_LEN(str)
Definition: ruby.h:1005
rb_attr
void rb_attr(VALUE, ID, int, int, int)
Definition: vm_method.c:1163
rb_define_alloc_func
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
RTEST
#define RTEST(v)
Definition: ruby.h:481
rb_iv_set
VALUE rb_iv_set(VALUE, const char *, VALUE)
Definition: variable.c:3307