Ruby 2.7.7p221 (2022-11-24 revision 168ec2b1e5ad0e4688e963d9de019557c78feed9)
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
47static void
48ossl_x509ext_free(void *ptr)
49{
50 X509_EXTENSION_free(ptr);
51}
52
53static 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 */
65ossl_x509ext_new(X509_EXTENSION *ext)
66{
67 X509_EXTENSION *new;
68 VALUE obj;
69
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
84X509_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 */
100static void
101ossl_x509extfactory_free(void *ctx)
102{
103 OPENSSL_free(ctx);
104}
105
106static const rb_data_type_t ossl_x509extfactory_type = {
107 "OpenSSL/X509/EXTENSION/Factory",
108 {
109 0, ossl_x509extfactory_free,
110 },
112};
113
114static VALUE
115ossl_x509extfactory_alloc(VALUE klass)
116{
117 X509V3_CTX *ctx;
118 VALUE obj;
119
121 rb_iv_set(obj, "@config", Qnil);
122
123 return obj;
124}
125
126static VALUE
127ossl_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
138static VALUE
139ossl_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
150static VALUE
151ossl_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
162static VALUE
163ossl_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
174static VALUE
175ossl_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 */
203static VALUE
204ossl_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);
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 */
245static VALUE
246ossl_x509ext_alloc(VALUE klass)
247{
248 X509_EXTENSION *ext;
249 VALUE obj;
250
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 */
272static VALUE
273ossl_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
297static VALUE
298ossl_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
316static VALUE
317ossl_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
335static VALUE
336ossl_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
354static VALUE
355ossl_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
365static VALUE
366ossl_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
388static VALUE
389ossl_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
405static VALUE
406ossl_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
414static VALUE
415ossl_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)
430
431 return str;
432}
433
434/*
435 * INIT
436 */
437void
439{
440#undef rb_intern
441#if 0
442 mOSSL = rb_define_module("OpenSSL");
445#endif
446
448
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
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}
struct RIMemo * ptr
Definition: debug.c:65
char str[HTML_ESCAPE_MAX_LEN+1]
Definition: escape.c:18
VALUE rb_define_class_under(VALUE, const char *, VALUE)
Defines a class under the namespace of outer.
Definition: class.c:711
VALUE rb_define_module(const char *)
Definition: class.c:785
VALUE rb_define_module_under(VALUE, const char *)
Definition: class.c:810
VALUE rb_cObject
Object class.
Definition: ruby.h:2012
VALUE rb_eStandardError
Definition: error.c:921
int nid
VALUE mOSSL
Definition: ossl.c:231
VALUE ossl_to_der_if_possible(VALUE obj)
Definition: ossl.c:255
void ossl_raise(VALUE exc, const char *fmt,...)
Definition: ossl.c:293
VALUE eOSSLError
Definition: ossl.c:236
#define ossl_str_adjust(str, p)
Definition: ossl.h:87
VALUE ossl_membio2str(BIO *bio)
Definition: ossl_bio.c:29
CONF * DupConfigPtr(VALUE obj)
Definition: ossl_config.c:35
VALUE mX509
Definition: ossl_x509.c:12
X509_REQ * GetX509ReqPtr(VALUE)
Definition: ossl_x509req.c:51
X509 * GetX509CertPtr(VALUE)
Definition: ossl_x509cert.c:71
X509_CRL * GetX509CRLPtr(VALUE)
Definition: ossl_x509crl.c:51
#define GetX509ExtFactory(obj, ctx)
Definition: ossl_x509ext.c:33
#define SetX509Ext(obj, ext)
Definition: ossl_x509ext.c:14
void Init_ossl_x509ext(void)
Definition: ossl_x509ext.c:438
VALUE eX509ExtError
Definition: ossl_x509ext.c:45
#define NewX509Ext(klass)
Definition: ossl_x509ext.c:12
#define MakeX509ExtFactory(klass, obj, ctx)
Definition: ossl_x509ext.c:26
VALUE cX509Ext
Definition: ossl_x509ext.c:43
VALUE cX509ExtFactory
Definition: ossl_x509ext.c:44
#define GetX509Ext(obj, ext)
Definition: ossl_x509ext.c:20
VALUE ossl_x509ext_new(X509_EXTENSION *ext)
Definition: ossl_x509ext.c:65
X509_EXTENSION * GetX509ExtPtr(VALUE obj)
Definition: ossl_x509ext.c:85
#define rb_str_new2
#define NULL
use StringValue() instead")))
#define RSTRING_LEN(str)
#define RTEST(v)
void rb_attr(VALUE, ID, int, int, int)
Definition: vm_method.c:1180
const VALUE VALUE obj
#define rb_check_frozen(obj)
#define RSTRING_PTR(str)
#define rb_str_new(str, len)
#define NIL_P(v)
#define RSTRING_LENINT(str)
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
__inline__ const void *__restrict__ size_t len
VALUE rb_iv_set(VALUE, const char *, VALUE)
Definition: variable.c:3318
#define RUBY_TYPED_FREE_IMMEDIATELY
#define PRIsVALUE
#define rb_funcall(recv, mid, argc,...)
#define rb_scan_args(argc, argvp, fmt,...)
#define rb_intern(str)
#define Qtrue
VALUE rb_str_append(VALUE, VALUE)
Definition: string.c:2965
#define Qnil
#define Qfalse
#define DATA_PTR(dta)
const VALUE * argv
VALUE rb_iv_get(VALUE, const char *)
Definition: variable.c:3305
void rb_define_method(VALUE, const char *, VALUE(*)(), int)
#define StringValueCStr(v)
unsigned long VALUE
Definition: ruby.h:102