Ruby  2.5.0dev(2017-10-22revision60238)
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, *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))) {
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()))) {
130  }
131  if (!PEM_write_bio_X509_REQ(out, req)) {
132  BIO_free(out);
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)
150  str = rb_str_new(0, len);
151  p = (unsigned char *)RSTRING_PTR(str);
152  if (i2d_X509_REQ(req, &p) <= 0)
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()))) {
168  }
169  if (!X509_REQ_print(out, req)) {
170  BIO_free(out);
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))) {
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 */
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))) {
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()))) {
265  }
266  X509_REQ_get0_signature(req, NULL, &alg);
267  if (!i2a_ASN1_OBJECT(out, alg->algorithm)) {
268  BIO_free(out);
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 */
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); /* NO NEED TO DUP */
297  if (!X509_REQ_set_pubkey(req, pkey)) {
299  }
300 
301  return key;
302 }
303 
304 static VALUE
305 ossl_x509req_sign(VALUE self, VALUE key, VALUE digest)
306 {
307  X509_REQ *req;
308  EVP_PKEY *pkey;
309  const EVP_MD *md;
310 
311  GetX509Req(self, req);
312  pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */
313  md = ossl_evp_get_digestbyname(digest);
314  if (!X509_REQ_sign(req, pkey, md)) {
316  }
317 
318  return self;
319 }
320 
321 /*
322  * Checks that cert signature is made with PRIVversion of this PUBLIC 'key'
323  */
324 static VALUE
325 ossl_x509req_verify(VALUE self, VALUE key)
326 {
327  X509_REQ *req;
328  EVP_PKEY *pkey;
329 
330  GetX509Req(self, req);
331  pkey = GetPKeyPtr(key); /* NO NEED TO DUP */
332  switch (X509_REQ_verify(req, pkey)) {
333  case 1:
334  return Qtrue;
335  case 0:
337  return Qfalse;
338  default:
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++) {
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)) {
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))) {
400  }
401 
402  return attr;
403 }
404 
405 /*
406  * X509_REQUEST init
407  */
408 void
410 {
411 #if 0
412  mOSSL = rb_define_module("OpenSSL");
415 #endif
416 
418 
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 }
VALUE mOSSL
Definition: ossl.c:231
#define RARRAY_LEN(a)
Definition: ruby.h:1019
#define RUBY_TYPED_FREE_IMMEDIATELY
Definition: ruby.h:1138
int count
Definition: encoding.c:56
#define Qtrue
Definition: ruby.h:437
void Init_ossl_x509req(void)
Definition: ossl_x509req.c:409
EVP_PKEY * GetPrivPKeyPtr(VALUE obj)
Definition: ossl_pkey.c:216
#define ossl_str_adjust(str, p)
Definition: ossl.h:82
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:924
BIO * ossl_obj2bio(volatile VALUE *pobj)
Definition: ossl_bio.c:13
X509_ATTRIBUTE * GetX509AttrPtr(VALUE)
Definition: ossl_x509attr.c:71
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:693
#define Check_Type(v, t)
Definition: ruby.h:562
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
VALUE cX509Req
Definition: ossl_x509req.c:30
#define DATA_PTR(dta)
Definition: ruby.h:1106
#define T_ARRAY
Definition: ruby.h:498
VALUE ossl_membio2str(BIO *bio)
Definition: ossl_bio.c:29
VALUE ossl_pkey_new(EVP_PKEY *pkey)
Definition: ossl_pkey.c:107
X509_NAME * GetX509NamePtr(VALUE)
Definition: ossl_x509name.c:76
#define rb_ary_new2
Definition: intern.h:90
VALUE eX509ReqError
Definition: ossl_x509req.c:31
const unsigned char * in
Definition: ossl_ssl.c:617
VALUE ossl_to_der_if_possible(VALUE obj)
Definition: ossl.c:255
#define X509_REQ_get0_signature
void ossl_clear_error(void)
Definition: ossl.c:304
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:1893
VALUE rb_ary_new(void)
Definition: array.c:499
#define OSSL_BIO_reset(bio)
Definition: ossl.h:110
VALUE eOSSLError
Definition: ossl.c:236
int argc
Definition: ruby.c:187
#define Qfalse
Definition: ruby.h:436
VALUE ossl_x509_new(X509 *)
Definition: ossl_x509cert.c:51
#define NewX509Req(klass)
Definition: ossl_x509req.c:12
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
Definition: class.c:1758
const EVP_MD * ossl_evp_get_digestbyname(VALUE obj)
Definition: ossl_digest.c:45
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1908
VALUE rb_eStandardError
Definition: error.c:799
unsigned long VALUE
Definition: ruby.h:85
VALUE mX509
Definition: ossl_x509.c:12
#define OSSL_Debug
Definition: ossl.h:144
#define LONG2NUM(x)
Definition: ruby.h:1573
register unsigned int len
Definition: zonetab.h:51
VALUE rb_define_module_under(VALUE outer, const char *name)
Definition: class.c:790
#define RSTRING_PTR(str)
Definition: ruby.h:975
VALUE ossl_x509attr_new(X509_ATTRIBUTE *)
Definition: ossl_x509attr.c:51
#define RARRAY_AREF(a, i)
Definition: ruby.h:1033
#define OSSL_Check_Kind(obj, klass)
Definition: ossl.h:52
#define GetX509Req(obj, req)
Definition: ossl_x509req.c:20
X509_REQ * GetX509ReqPtr(VALUE obj)
Definition: ossl_x509req.c:51
void ossl_raise(VALUE exc, const char *fmt,...)
Definition: ossl.c:293
EVP_PKEY * GetPKeyPtr(VALUE obj)
Definition: ossl_pkey.c:206
const char * name
Definition: nkf.c:208
VALUE ossl_x509name_new(X509_NAME *)
Definition: ossl_x509name.c:56
#define rb_check_frozen(obj)
Definition: intern.h:271
VALUE rb_define_module(const char *name)
Definition: class.c:768
#define NULL
Definition: _sdbm.c:102
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1515
#define SetX509Req(obj, req)
Definition: ossl_x509req.c:14
#define NUM2LONG(x)
Definition: ruby.h:648
VALUE cX509Attr
Definition: ossl_x509attr.c:30
char ** argv
Definition: ruby.c:188
VALUE rb_str_new(const char *, long)
Definition: string.c:737