Ruby  3.1.0dev(2021-09-10revisionb76ad15ed0da636161de0243c547ee1e6fc95681)
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  */
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  },
45 };
46 
47 /*
48  * Public functions
49  */
50 X509_REQ *
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())) {
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, *req_orig = RTYPEDDATA_DATA(self);
83  VALUE arg;
84 
85  rb_check_frozen(self);
86  if (rb_scan_args(argc, argv, "01", &arg) == 0) {
87  return self;
88  }
89  arg = ossl_to_der_if_possible(arg);
90  in = ossl_obj2bio(&arg);
91  req = d2i_X509_REQ_bio(in, NULL);
92  if (!req) {
93  OSSL_BIO_reset(in);
94  req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL);
95  }
96  BIO_free(in);
97  if (!req)
98  ossl_raise(eX509ReqError, "PEM_read_bio_X509_REQ");
99 
100  RTYPEDDATA_DATA(self) = req;
101  X509_REQ_free(req_orig);
102 
103  return self;
104 }
105 
106 static VALUE
107 ossl_x509req_copy(VALUE self, VALUE other)
108 {
109  X509_REQ *a, *b, *req;
110 
111  rb_check_frozen(self);
112  if (self == other) return self;
113  GetX509Req(self, a);
114  GetX509Req(other, b);
115  if (!(req = X509_REQ_dup(b))) {
117  }
118  X509_REQ_free(a);
119  DATA_PTR(self) = req;
120 
121  return self;
122 }
123 
124 static VALUE
125 ossl_x509req_to_pem(VALUE self)
126 {
127  X509_REQ *req;
128  BIO *out;
129 
130  GetX509Req(self, req);
131  if (!(out = BIO_new(BIO_s_mem()))) {
133  }
134  if (!PEM_write_bio_X509_REQ(out, req)) {
135  BIO_free(out);
137  }
138 
139  return ossl_membio2str(out);
140 }
141 
142 static VALUE
143 ossl_x509req_to_der(VALUE self)
144 {
145  X509_REQ *req;
146  VALUE str;
147  long len;
148  unsigned char *p;
149 
150  GetX509Req(self, req);
151  if ((len = i2d_X509_REQ(req, NULL)) <= 0)
153  str = rb_str_new(0, len);
154  p = (unsigned char *)RSTRING_PTR(str);
155  if (i2d_X509_REQ(req, &p) <= 0)
157  ossl_str_adjust(str, p);
158 
159  return str;
160 }
161 
162 static VALUE
163 ossl_x509req_to_text(VALUE self)
164 {
165  X509_REQ *req;
166  BIO *out;
167 
168  GetX509Req(self, req);
169  if (!(out = BIO_new(BIO_s_mem()))) {
171  }
172  if (!X509_REQ_print(out, req)) {
173  BIO_free(out);
175  }
176 
177  return ossl_membio2str(out);
178 }
179 
180 #if 0
181 /*
182  * Makes X509 from X509_REQuest
183  */
184 static VALUE
185 ossl_x509req_to_x509(VALUE self, VALUE days, VALUE key)
186 {
187  X509_REQ *req;
188  X509 *x509;
189 
190  GetX509Req(self, req);
191  ...
192  if (!(x509 = X509_REQ_to_X509(req, d, pkey))) {
194  }
195 
196  return ossl_x509_new(x509);
197 }
198 #endif
199 
200 static VALUE
201 ossl_x509req_get_version(VALUE self)
202 {
203  X509_REQ *req;
204  long version;
205 
206  GetX509Req(self, req);
207  version = X509_REQ_get_version(req);
208 
209  return LONG2NUM(version);
210 }
211 
212 static VALUE
213 ossl_x509req_set_version(VALUE self, VALUE version)
214 {
215  X509_REQ *req;
216  long ver;
217 
218  if ((ver = NUM2LONG(version)) < 0) {
219  ossl_raise(eX509ReqError, "version must be >= 0!");
220  }
221  GetX509Req(self, req);
222  if (!X509_REQ_set_version(req, ver)) {
223  ossl_raise(eX509ReqError, "X509_REQ_set_version");
224  }
225 
226  return version;
227 }
228 
229 static VALUE
230 ossl_x509req_get_subject(VALUE self)
231 {
232  X509_REQ *req;
233  X509_NAME *name;
234 
235  GetX509Req(self, req);
236  if (!(name = X509_REQ_get_subject_name(req))) { /* NO DUP - don't free */
238  }
239 
240  return ossl_x509name_new(name);
241 }
242 
243 static VALUE
244 ossl_x509req_set_subject(VALUE self, VALUE subject)
245 {
246  X509_REQ *req;
247 
248  GetX509Req(self, req);
249  /* DUPs name */
250  if (!X509_REQ_set_subject_name(req, GetX509NamePtr(subject))) {
252  }
253 
254  return subject;
255 }
256 
257 static VALUE
258 ossl_x509req_get_signature_algorithm(VALUE self)
259 {
260  X509_REQ *req;
261  const X509_ALGOR *alg;
262  BIO *out;
263 
264  GetX509Req(self, req);
265 
266  if (!(out = BIO_new(BIO_s_mem()))) {
268  }
269  X509_REQ_get0_signature(req, NULL, &alg);
270  if (!i2a_ASN1_OBJECT(out, alg->algorithm)) {
271  BIO_free(out);
273  }
274 
275  return ossl_membio2str(out);
276 }
277 
278 static VALUE
279 ossl_x509req_get_public_key(VALUE self)
280 {
281  X509_REQ *req;
282  EVP_PKEY *pkey;
283 
284  GetX509Req(self, req);
285  if (!(pkey = X509_REQ_get_pubkey(req))) { /* adds reference */
287  }
288 
289  return ossl_pkey_new(pkey); /* NO DUP - OK */
290 }
291 
292 static VALUE
293 ossl_x509req_set_public_key(VALUE self, VALUE key)
294 {
295  X509_REQ *req;
296  EVP_PKEY *pkey;
297 
298  GetX509Req(self, req);
299  pkey = GetPKeyPtr(key);
301  if (!X509_REQ_set_pubkey(req, pkey))
302  ossl_raise(eX509ReqError, "X509_REQ_set_pubkey");
303  return key;
304 }
305 
306 static VALUE
307 ossl_x509req_sign(VALUE self, VALUE key, VALUE digest)
308 {
309  X509_REQ *req;
310  EVP_PKEY *pkey;
311  const EVP_MD *md;
312 
313  GetX509Req(self, req);
314  pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */
315  md = ossl_evp_get_digestbyname(digest);
316  if (!X509_REQ_sign(req, pkey, md)) {
318  }
319 
320  return self;
321 }
322 
323 /*
324  * Checks that cert signature is made with PRIVversion of this PUBLIC 'key'
325  */
326 static VALUE
327 ossl_x509req_verify(VALUE self, VALUE key)
328 {
329  X509_REQ *req;
330  EVP_PKEY *pkey;
331 
332  GetX509Req(self, req);
333  pkey = GetPKeyPtr(key);
335  switch (X509_REQ_verify(req, pkey)) {
336  case 1:
337  return Qtrue;
338  case 0:
340  return Qfalse;
341  default:
343  }
344 }
345 
346 static VALUE
347 ossl_x509req_get_attributes(VALUE self)
348 {
349  X509_REQ *req;
350  int count, i;
351  X509_ATTRIBUTE *attr;
352  VALUE ary;
353 
354  GetX509Req(self, req);
355 
356  count = X509_REQ_get_attr_count(req);
357  if (count < 0) {
358  OSSL_Debug("count < 0???");
359  return rb_ary_new();
360  }
361  ary = rb_ary_new2(count);
362  for (i=0; i<count; i++) {
363  attr = X509_REQ_get_attr(req, i);
364  rb_ary_push(ary, ossl_x509attr_new(attr));
365  }
366 
367  return ary;
368 }
369 
370 static VALUE
371 ossl_x509req_set_attributes(VALUE self, VALUE ary)
372 {
373  X509_REQ *req;
374  X509_ATTRIBUTE *attr;
375  long i;
376  VALUE item;
377 
378  Check_Type(ary, T_ARRAY);
379  for (i=0;i<RARRAY_LEN(ary); i++) {
381  }
382  GetX509Req(self, req);
383  while ((attr = X509_REQ_delete_attr(req, 0)))
384  X509_ATTRIBUTE_free(attr);
385  for (i=0;i<RARRAY_LEN(ary); i++) {
386  item = RARRAY_AREF(ary, i);
387  attr = GetX509AttrPtr(item);
388  if (!X509_REQ_add1_attr(req, attr)) {
390  }
391  }
392  return ary;
393 }
394 
395 static VALUE
396 ossl_x509req_add_attribute(VALUE self, VALUE attr)
397 {
398  X509_REQ *req;
399 
400  GetX509Req(self, req);
401  if (!X509_REQ_add1_attr(req, GetX509AttrPtr(attr))) {
403  }
404 
405  return attr;
406 }
407 
408 /*
409  * X509_REQUEST init
410  */
411 void
413 {
414 #if 0
415  mOSSL = rb_define_module("OpenSSL");
418 #endif
419 
421 
423 
424  rb_define_alloc_func(cX509Req, ossl_x509req_alloc);
425  rb_define_method(cX509Req, "initialize", ossl_x509req_initialize, -1);
426  rb_define_method(cX509Req, "initialize_copy", ossl_x509req_copy, 1);
427 
428  rb_define_method(cX509Req, "to_pem", ossl_x509req_to_pem, 0);
429  rb_define_method(cX509Req, "to_der", ossl_x509req_to_der, 0);
430  rb_define_alias(cX509Req, "to_s", "to_pem");
431  rb_define_method(cX509Req, "to_text", ossl_x509req_to_text, 0);
432  rb_define_method(cX509Req, "version", ossl_x509req_get_version, 0);
433  rb_define_method(cX509Req, "version=", ossl_x509req_set_version, 1);
434  rb_define_method(cX509Req, "subject", ossl_x509req_get_subject, 0);
435  rb_define_method(cX509Req, "subject=", ossl_x509req_set_subject, 1);
436  rb_define_method(cX509Req, "signature_algorithm", ossl_x509req_get_signature_algorithm, 0);
437  rb_define_method(cX509Req, "public_key", ossl_x509req_get_public_key, 0);
438  rb_define_method(cX509Req, "public_key=", ossl_x509req_set_public_key, 1);
439  rb_define_method(cX509Req, "sign", ossl_x509req_sign, 2);
440  rb_define_method(cX509Req, "verify", ossl_x509req_verify, 1);
441  rb_define_method(cX509Req, "attributes", ossl_x509req_get_attributes, 0);
442  rb_define_method(cX509Req, "attributes=", ossl_x509req_set_attributes, 1);
443  rb_define_method(cX509Req, "add_attribute", ossl_x509req_add_attribute, 1);
444 }
GetPKeyPtr
EVP_PKEY * GetPKeyPtr(VALUE obj)
Definition: ossl_pkey.c:432
Init_ossl_x509req
void Init_ossl_x509req(void)
Definition: ossl_x509req.c:412
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:914
ossl_x509name_new
VALUE ossl_x509name_new(X509_NAME *)
Definition: ossl_x509name.c:56
ossl_to_der_if_possible
VALUE ossl_to_der_if_possible(VALUE obj)
Definition: ossl.c:261
ossl_membio2str
VALUE ossl_membio2str(BIO *bio)
Definition: ossl_bio.c:29
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:58
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:51
OSSL_BIO_reset
#define OSSL_BIO_reset(bio)
Definition: ossl.h:115
eX509ReqError
VALUE eX509ReqError
Definition: ossl_x509req.c:31
rb_define_module
VALUE rb_define_module(const char *name)
Definition: class.c:887
mX509
VALUE mX509
Definition: ossl_x509.c:12
LONG2NUM
#define LONG2NUM
Definition: long.h:50
ossl.h
argv
char ** argv
Definition: ruby.c:243
ossl_clear_error
void ossl_clear_error(void)
Definition: ossl.c:310
ptr
struct RIMemo * ptr
Definition: debug.c:87
cX509Attr
VALUE cX509Attr
Definition: ossl_x509attr.c:30
ossl_str_adjust
#define ossl_str_adjust(str, p)
Definition: ossl.h:88
rb_define_alias
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
Definition: class.c:2050
rb_str_new
#define rb_str_new(str, len)
Definition: string.h:213
ossl_pkey_check_public_key
void ossl_pkey_check_public_key(const EVP_PKEY *pkey)
Definition: ossl_pkey.c:392
RUBY_TYPED_FREE_IMMEDIATELY
@ RUBY_TYPED_FREE_IMMEDIATELY
Definition: rtypeddata.h:62
cX509Req
VALUE cX509Req
Definition: ossl_x509req.c:30
mOSSL
VALUE mOSSL
Definition: ossl.c:237
rb_define_alloc_func
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
rb_cObject
VALUE rb_cObject
Object class.
Definition: object.c:50
NewX509Req
#define NewX509Req(klass)
Definition: ossl_x509req.c:12
Qfalse
#define Qfalse
Definition: special_consts.h:50
len
uint8_t len
Definition: escape.c:17
rb_ary_push
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:1312
ossl_raise
void ossl_raise(VALUE exc, const char *fmt,...)
Definition: ossl.c:299
GetX509AttrPtr
X509_ATTRIBUTE * GetX509AttrPtr(VALUE)
Definition: ossl_x509attr.c:71
NULL
#define NULL
Definition: regenc.h:69
RTYPEDDATA_DATA
#define RTYPEDDATA_DATA(v)
Definition: rtypeddata.h:47
rb_scan_args
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:2347
GetX509Req
#define GetX509Req(obj, req)
Definition: ossl_x509req.c:20
key
key
Definition: openssl_missing.h:145
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
Qtrue
#define Qtrue
Definition: special_consts.h:52
rb_ary_new2
#define rb_ary_new2
Definition: array.h:72
VALUE
unsigned long VALUE
Definition: value.h:38
RSTRING_PTR
#define RSTRING_PTR(string)
Definition: fbuffer.h:19
str
char str[HTML_ESCAPE_MAX_LEN+1]
Definition: escape.c:18
OSSL_Debug
#define OSSL_Debug(...)
Definition: ossl.h:139
NUM2LONG
#define NUM2LONG
Definition: long.h:51
GetX509NamePtr
X509_NAME * GetX509NamePtr(VALUE)
Definition: ossl_x509name.c:76
rb_check_frozen
#define rb_check_frozen
Definition: error.h:72
argc
int argc
Definition: ruby.c:242
T_ARRAY
#define T_ARRAY
Definition: value_type.h:56
rb_data_type_struct
Definition: rtypeddata.h:70
RARRAY_AREF
#define RARRAY_AREF(a, i)
Definition: missing.h:201
count
int count
Definition: nkf.c:5055
eOSSLError
VALUE eOSSLError
Definition: ossl.c:242
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:809
DATA_PTR
#define DATA_PTR(obj)
Definition: rdata.h:55
rb_define_method
#define rb_define_method(klass, mid, func, arity)
Defines klass#mid.
Definition: cxxanyargs.hpp:655
RARRAY_LEN
#define RARRAY_LEN
Definition: rarray.h:52
rb_ary_new
VALUE rb_ary_new(void)
Definition: array.c:754
GetPrivPKeyPtr
EVP_PKEY * GetPrivPKeyPtr(VALUE obj)
Definition: ossl_pkey.c:442
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:1090
ossl_pkey_new
VALUE ossl_pkey_new(EVP_PKEY *pkey)
Definition: ossl_pkey.c:67
name
const char * name
Definition: nkf.c:208