Ruby 2.7.0p0(2019-12-25revision647ee6f091eafcce70ffb75ddf7e121e192ab217)

ossl_x509req.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 NewX509Req(klass) \
13 TypedData_Wrap_Struct((klass), &ossl_x509req_type, 0)
14 #define SetX509Req(obj, req) do { \
15 if (!(req)) { \
16 ossl_raise(rb_eRuntimeError, "Req wasn't initialized!"); \
17 } \
18 RTYPEDDATA_DATA(obj) = (req); \
19 } while (0)
20 #define GetX509Req(obj, req) do { \
21 TypedData_Get_Struct((obj), X509_REQ, &ossl_x509req_type, (req)); \
22 if (!(req)) { \
23 ossl_raise(rb_eRuntimeError, "Req wasn't initialized!"); \
24 } \
25 } while (0)
26
27 /*
28 * Classes
29 */
30 VALUE cX509Req;
31 VALUE eX509ReqError;
32
33 static void
34 ossl_x509req_free(void *ptr)
35 {
36 X509_REQ_free(ptr);
37 }
38
39 static const rb_data_type_t ossl_x509req_type = {
40 "OpenSSL/X509/REQ",
41 {
42 0, ossl_x509req_free,
43 },
44 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
45 };
46
47 /*
48 * Public functions
49 */
50 X509_REQ *
51 GetX509ReqPtr(VALUE obj)
52 {
53 X509_REQ *req;
54
55 GetX509Req(obj, req);
56
57 return req;
58 }
59
60 /*
61 * Private functions
62 */
63 static VALUE
64 ossl_x509req_alloc(VALUE klass)
65 {
66 X509_REQ *req;
67 VALUE obj;
68
69 obj = NewX509Req(klass);
70 if (!(req = X509_REQ_new())) {
71 ossl_raise(eX509ReqError, NULL);
72 }
73 SetX509Req(obj, req);
74
75 return obj;
76 }
77
78 static VALUE
79 ossl_x509req_initialize(int argc, VALUE *argv, VALUE self)
80 {
81 BIO *in;
82 X509_REQ *req, *x = DATA_PTR(self);
83 VALUE arg;
84
85 if (rb_scan_args(argc, argv, "01", &arg) == 0) {
86 return self;
87 }
88 arg = ossl_to_der_if_possible(arg);
89 in = ossl_obj2bio(&arg);
90 req = PEM_read_bio_X509_REQ(in, &x, NULL, NULL);
91 DATA_PTR(self) = x;
92 if (!req) {
93 OSSL_BIO_reset(in);
94 req = d2i_X509_REQ_bio(in, &x);
95 DATA_PTR(self) = x;
96 }
97 BIO_free(in);
98 if (!req) ossl_raise(eX509ReqError, NULL);
99
100 return self;
101 }
102
103 static VALUE
104 ossl_x509req_copy(VALUE self, VALUE other)
105 {
106 X509_REQ *a, *b, *req;
107
108 rb_check_frozen(self);
109 if (self == other) return self;
110 GetX509Req(self, a);
111 GetX509Req(other, b);
112 if (!(req = X509_REQ_dup(b))) {
113 ossl_raise(eX509ReqError, NULL);
114 }
115 X509_REQ_free(a);
116 DATA_PTR(self) = req;
117
118 return self;
119 }
120
121 static VALUE
122 ossl_x509req_to_pem(VALUE self)
123 {
124 X509_REQ *req;
125 BIO *out;
126
127 GetX509Req(self, req);
128 if (!(out = BIO_new(BIO_s_mem()))) {
129 ossl_raise(eX509ReqError, NULL);
130 }
131 if (!PEM_write_bio_X509_REQ(out, req)) {
132 BIO_free(out);
133 ossl_raise(eX509ReqError, NULL);
134 }
135
136 return ossl_membio2str(out);
137 }
138
139 static VALUE
140 ossl_x509req_to_der(VALUE self)
141 {
142 X509_REQ *req;
143 VALUE str;
144 long len;
145 unsigned char *p;
146
147 GetX509Req(self, req);
148 if ((len = i2d_X509_REQ(req, NULL)) <= 0)
149 ossl_raise(eX509ReqError, NULL);
150 str = rb_str_new(0, len);
151 p = (unsigned char *)RSTRING_PTR(str);
152 if (i2d_X509_REQ(req, &p) <= 0)
153 ossl_raise(eX509ReqError, NULL);
154 ossl_str_adjust(str, p);
155
156 return str;
157 }
158
159 static VALUE
160 ossl_x509req_to_text(VALUE self)
161 {
162 X509_REQ *req;
163 BIO *out;
164
165 GetX509Req(self, req);
166 if (!(out = BIO_new(BIO_s_mem()))) {
167 ossl_raise(eX509ReqError, NULL);
168 }
169 if (!X509_REQ_print(out, req)) {
170 BIO_free(out);
171 ossl_raise(eX509ReqError, NULL);
172 }
173
174 return ossl_membio2str(out);
175 }
176
177 #if 0
178 /*
179 * Makes X509 from X509_REQuest
180 */
181 static VALUE
182 ossl_x509req_to_x509(VALUE self, VALUE days, VALUE key)
183 {
184 X509_REQ *req;
185 X509 *x509;
186
187 GetX509Req(self, req);
188 ...
189 if (!(x509 = X509_REQ_to_X509(req, d, pkey))) {
190 ossl_raise(eX509ReqError, NULL);
191 }
192
193 return ossl_x509_new(x509);
194 }
195 #endif
196
197 static VALUE
198 ossl_x509req_get_version(VALUE self)
199 {
200 X509_REQ *req;
201 long version;
202
203 GetX509Req(self, req);
204 version = X509_REQ_get_version(req);
205
206 return LONG2NUM(version);
207 }
208
209 static VALUE
210 ossl_x509req_set_version(VALUE self, VALUE version)
211 {
212 X509_REQ *req;
213 long ver;
214
215 if ((ver = NUM2LONG(version)) < 0) {
216 ossl_raise(eX509ReqError, "version must be >= 0!");
217 }
218 GetX509Req(self, req);
219 if (!X509_REQ_set_version(req, ver)) {
220 ossl_raise(eX509ReqError, "X509_REQ_set_version");
221 }
222
223 return version;
224 }
225
226 static VALUE
227 ossl_x509req_get_subject(VALUE self)
228 {
229 X509_REQ *req;
230 X509_NAME *name;
231
232 GetX509Req(self, req);
233 if (!(name = X509_REQ_get_subject_name(req))) { /* NO DUP - don't free */
234 ossl_raise(eX509ReqError, NULL);
235 }
236
237 return ossl_x509name_new(name);
238 }
239
240 static VALUE
241 ossl_x509req_set_subject(VALUE self, VALUE subject)
242 {
243 X509_REQ *req;
244
245 GetX509Req(self, req);
246 /* DUPs name */
247 if (!X509_REQ_set_subject_name(req, GetX509NamePtr(subject))) {
248 ossl_raise(eX509ReqError, NULL);
249 }
250
251 return subject;
252 }
253
254 static VALUE
255 ossl_x509req_get_signature_algorithm(VALUE self)
256 {
257 X509_REQ *req;
258 const X509_ALGOR *alg;
259 BIO *out;
260
261 GetX509Req(self, req);
262
263 if (!(out = BIO_new(BIO_s_mem()))) {
264 ossl_raise(eX509ReqError, NULL);
265 }
266 X509_REQ_get0_signature(req, NULL, &alg);
267 if (!i2a_ASN1_OBJECT(out, alg->algorithm)) {
268 BIO_free(out);
269 ossl_raise(eX509ReqError, NULL);
270 }
271
272 return ossl_membio2str(out);
273 }
274
275 static VALUE
276 ossl_x509req_get_public_key(VALUE self)
277 {
278 X509_REQ *req;
279 EVP_PKEY *pkey;
280
281 GetX509Req(self, req);
282 if (!(pkey = X509_REQ_get_pubkey(req))) { /* adds reference */
283 ossl_raise(eX509ReqError, NULL);
284 }
285
286 return ossl_pkey_new(pkey); /* NO DUP - OK */
287 }
288
289 static VALUE
290 ossl_x509req_set_public_key(VALUE self, VALUE key)
291 {
292 X509_REQ *req;
293 EVP_PKEY *pkey;
294
295 GetX509Req(self, req);
296 pkey = GetPKeyPtr(key);
297 ossl_pkey_check_public_key(pkey);
298 if (!X509_REQ_set_pubkey(req, pkey))
299 ossl_raise(eX509ReqError, "X509_REQ_set_pubkey");
300 return key;
301 }
302
303 static VALUE
304 ossl_x509req_sign(VALUE self, VALUE key, VALUE digest)
305 {
306 X509_REQ *req;
307 EVP_PKEY *pkey;
308 const EVP_MD *md;
309
310 GetX509Req(self, req);
311 pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */
312 md = ossl_evp_get_digestbyname(digest);
313 if (!X509_REQ_sign(req, pkey, md)) {
314 ossl_raise(eX509ReqError, NULL);
315 }
316
317 return self;
318 }
319
320 /*
321 * Checks that cert signature is made with PRIVversion of this PUBLIC 'key'
322 */
323 static VALUE
324 ossl_x509req_verify(VALUE self, VALUE key)
325 {
326 X509_REQ *req;
327 EVP_PKEY *pkey;
328
329 GetX509Req(self, req);
330 pkey = GetPKeyPtr(key);
331 ossl_pkey_check_public_key(pkey);
332 switch (X509_REQ_verify(req, pkey)) {
333 case 1:
334 return Qtrue;
335 case 0:
336 ossl_clear_error();
337 return Qfalse;
338 default:
339 ossl_raise(eX509ReqError, NULL);
340 }
341 }
342
343 static VALUE
344 ossl_x509req_get_attributes(VALUE self)
345 {
346 X509_REQ *req;
347 int count, i;
348 X509_ATTRIBUTE *attr;
349 VALUE ary;
350
351 GetX509Req(self, req);
352
353 count = X509_REQ_get_attr_count(req);
354 if (count < 0) {
355 OSSL_Debug("count < 0???");
356 return rb_ary_new();
357 }
358 ary = rb_ary_new2(count);
359 for (i=0; i<count; i++) {
360 attr = X509_REQ_get_attr(req, i);
361 rb_ary_push(ary, ossl_x509attr_new(attr));
362 }
363
364 return ary;
365 }
366
367 static VALUE
368 ossl_x509req_set_attributes(VALUE self, VALUE ary)
369 {
370 X509_REQ *req;
371 X509_ATTRIBUTE *attr;
372 long i;
373 VALUE item;
374
375 Check_Type(ary, T_ARRAY);
376 for (i=0;i<RARRAY_LEN(ary); i++) {
377 OSSL_Check_Kind(RARRAY_AREF(ary, i), cX509Attr);
378 }
379 GetX509Req(self, req);
380 while ((attr = X509_REQ_delete_attr(req, 0)))
381 X509_ATTRIBUTE_free(attr);
382 for (i=0;i<RARRAY_LEN(ary); i++) {
383 item = RARRAY_AREF(ary, i);
384 attr = GetX509AttrPtr(item);
385 if (!X509_REQ_add1_attr(req, attr)) {
386 ossl_raise(eX509ReqError, NULL);
387 }
388 }
389 return ary;
390 }
391
392 static VALUE
393 ossl_x509req_add_attribute(VALUE self, VALUE attr)
394 {
395 X509_REQ *req;
396
397 GetX509Req(self, req);
398 if (!X509_REQ_add1_attr(req, GetX509AttrPtr(attr))) {
399 ossl_raise(eX509ReqError, NULL);
400 }
401
402 return attr;
403 }
404
405 /*
406 * X509_REQUEST init
407 */
408 void
409 Init_ossl_x509req(void)
410 {
411 #if 0
412 mOSSL = rb_define_module("OpenSSL");
413 eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
414 mX509 = rb_define_module_under(mOSSL, "X509");
415 #endif
416
417 eX509ReqError = rb_define_class_under(mX509, "RequestError", eOSSLError);
418
419 cX509Req = rb_define_class_under(mX509, "Request", rb_cObject);
420
421 rb_define_alloc_func(cX509Req, ossl_x509req_alloc);
422 rb_define_method(cX509Req, "initialize", ossl_x509req_initialize, -1);
423 rb_define_method(cX509Req, "initialize_copy", ossl_x509req_copy, 1);
424
425 rb_define_method(cX509Req, "to_pem", ossl_x509req_to_pem, 0);
426 rb_define_method(cX509Req, "to_der", ossl_x509req_to_der, 0);
427 rb_define_alias(cX509Req, "to_s", "to_pem");
428 rb_define_method(cX509Req, "to_text", ossl_x509req_to_text, 0);
429 rb_define_method(cX509Req, "version", ossl_x509req_get_version, 0);
430 rb_define_method(cX509Req, "version=", ossl_x509req_set_version, 1);
431 rb_define_method(cX509Req, "subject", ossl_x509req_get_subject, 0);
432 rb_define_method(cX509Req, "subject=", ossl_x509req_set_subject, 1);
433 rb_define_method(cX509Req, "signature_algorithm", ossl_x509req_get_signature_algorithm, 0);
434 rb_define_method(cX509Req, "public_key", ossl_x509req_get_public_key, 0);
435 rb_define_method(cX509Req, "public_key=", ossl_x509req_set_public_key, 1);
436 rb_define_method(cX509Req, "sign", ossl_x509req_sign, 2);
437 rb_define_method(cX509Req, "verify", ossl_x509req_verify, 1);
438 rb_define_method(cX509Req, "attributes", ossl_x509req_get_attributes, 0);
439 rb_define_method(cX509Req, "attributes=", ossl_x509req_set_attributes, 1);
440 rb_define_method(cX509Req, "add_attribute", ossl_x509req_add_attribute, 1);
441 }
Check_Type
#define Check_Type(v, t)
Definition: ruby.h:595
GetPKeyPtr
EVP_PKEY * GetPKeyPtr(VALUE obj)
Definition: ossl_pkey.c:229
Init_ossl_x509req
void Init_ossl_x509req(void)
Definition: ossl_x509req.c:409
SetX509Req
#define SetX509Req(obj, req)
Definition: ossl_x509req.c:14
rb_define_module_under
VALUE rb_define_module_under(VALUE outer, const char *name)
Definition: class.c:797
ossl_x509name_new
VALUE ossl_x509name_new(X509_NAME *)
Definition: ossl_x509name.c:56
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
NUM2LONG
#define NUM2LONG(x)
Definition: ruby.h:679
ossl_membio2str
VALUE ossl_membio2str(BIO *bio)
Definition: ossl_bio.c:29
VALUE
unsigned long VALUE
Definition: ruby.h:102
ossl_obj2bio
BIO * ossl_obj2bio(volatile VALUE *pobj)
Definition: ossl_bio.c:13
OSSL_Check_Kind
#define OSSL_Check_Kind(obj, klass)
Definition: ossl.h:56
ossl_x509_new
VALUE ossl_x509_new(X509 *)
Definition: ossl_x509cert.c:51
X509_REQ_get0_signature
#define X509_REQ_get0_signature
Definition: openssl_missing.h:87
OSSL_BIO_reset
#define OSSL_BIO_reset(bio)
Definition: ossl.h:114
eX509ReqError
VALUE eX509ReqError
Definition: ossl_x509req.c:31
rb_define_module
VALUE rb_define_module(const char *name)
Definition: class.c:772
mX509
VALUE mX509
Definition: ossl_x509.c:12
ossl.h
ossl_clear_error
void ossl_clear_error(void)
Definition: ossl.c:304
rb_define_method
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1551
ptr
struct RIMemo * ptr
Definition: debug.c:74
cX509Attr
VALUE cX509Attr
Definition: ossl_x509attr.c:30
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
rb_define_alias
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
Definition: class.c:1800
ossl_pkey_check_public_key
void ossl_pkey_check_public_key(const EVP_PKEY *pkey)
Definition: ossl_pkey.c:189
LONG2NUM
#define LONG2NUM(x)
Definition: ruby.h:1644
obj
const VALUE VALUE obj
Definition: rb_mjit_min_header-2.7.0.h:5742
cX509Req
VALUE cX509Req
Definition: ossl_x509req.c:30
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
i
uint32_t i
Definition: rb_mjit_min_header-2.7.0.h:5464
NewX509Req
#define NewX509Req(klass)
Definition: ossl_x509req.c:12
rb_ary_push
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:1195
OSSL_Debug
#define OSSL_Debug
Definition: ossl.h:148
ossl_raise
void ossl_raise(VALUE exc, const char *fmt,...)
Definition: ossl.c:293
GetX509AttrPtr
X509_ATTRIBUTE * GetX509AttrPtr(VALUE)
Definition: ossl_x509attr.c:71
RARRAY_AREF
#define RARRAY_AREF(a, i)
Definition: ruby.h:1101
GetX509Req
#define GetX509Req(obj, req)
Definition: ossl_x509req.c:20
key
key
Definition: openssl_missing.h:181
ossl_x509attr_new
VALUE ossl_x509attr_new(X509_ATTRIBUTE *)
Definition: ossl_x509attr.c:51
GetX509ReqPtr
X509_REQ * GetX509ReqPtr(VALUE obj)
Definition: ossl_x509req.c:51
RARRAY_LEN
#define RARRAY_LEN(a)
Definition: ruby.h:1070
npn_select_cb_common_args::in
const unsigned char * in
Definition: ossl_ssl.c:618
rb_cObject
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:2010
rb_ary_new2
#define rb_ary_new2
Definition: intern.h:103
T_ARRAY
#define T_ARRAY
Definition: ruby.h:530
arg
VALUE arg
Definition: rb_mjit_min_header-2.7.0.h:5601
argv
char ** argv
Definition: ruby.c:223
klass
VALUE klass
Definition: rb_mjit_min_header-2.7.0.h:13254
str
char str[HTML_ESCAPE_MAX_LEN+1]
Definition: escape.c:18
GetX509NamePtr
X509_NAME * GetX509NamePtr(VALUE)
Definition: ossl_x509name.c:76
RUBY_TYPED_FREE_IMMEDIATELY
#define RUBY_TYPED_FREE_IMMEDIATELY
Definition: ruby.h:1207
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
count
int count
Definition: encoding.c:57
Qtrue
#define Qtrue
Definition: ruby.h:468
len
uint8_t len
Definition: escape.c:17
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
rb_ary_new
VALUE rb_ary_new(void)
Definition: array.c:723
GetPrivPKeyPtr
EVP_PKEY * GetPrivPKeyPtr(VALUE obj)
Definition: ossl_pkey.c:239
ossl_evp_get_digestbyname
const EVP_MD * ossl_evp_get_digestbyname(VALUE obj)
Definition: ossl_digest.c:45
rb_eStandardError
VALUE rb_eStandardError
Definition: error.c:919
rb_define_alloc_func
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
ossl_pkey_new
VALUE ossl_pkey_new(EVP_PKEY *pkey)
Definition: ossl_pkey.c:129
name
const char * name
Definition: nkf.c:208