Ruby 2.0.0p247(2013-06-27revision41674)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

ossl_x509req.c
Go to the documentation of this file.
1 /*
2 * $Id: ossl_x509req.c 32199 2011-06-22 08:41:08Z emboss $
3 * 'OpenSSL for Ruby' project
4 * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
5 * All rights reserved.
6 */
7 /*
8 * This program is licenced under the same licence as Ruby.
9 * (See the file 'LICENCE'.)
10 */
11 #include "ossl.h"
12
13 #define WrapX509Req(klass, obj, req) do { \
14 if (!(req)) { \
15 ossl_raise(rb_eRuntimeError, "Req wasn't initialized!"); \
16 } \
17 (obj) = Data_Wrap_Struct((klass), 0, X509_REQ_free, (req)); \
18 } while (0)
19 #define GetX509Req(obj, req) do { \
20 Data_Get_Struct((obj), X509_REQ, (req)); \
21 if (!(req)) { \
22 ossl_raise(rb_eRuntimeError, "Req wasn't initialized!"); \
23 } \
24 } while (0)
25 #define SafeGetX509Req(obj, req) do { \
26 OSSL_Check_Kind((obj), cX509Req); \
27 GetX509Req((obj), (req)); \
28 } while (0)
29
30 /*
31 * Classes
32 */
33 VALUE cX509Req;
34 VALUE eX509ReqError;
35
36 /*
37 * Public functions
38 */
39 VALUE
40 ossl_x509req_new(X509_REQ *req)
41 {
42 X509_REQ *new;
43 VALUE obj;
44
45 if (!req) {
46 new = X509_REQ_new();
47 } else {
48 new = X509_REQ_dup(req);
49 }
50 if (!new) {
51 ossl_raise(eX509ReqError, NULL);
52 }
53 WrapX509Req(cX509Req, obj, new);
54
55 return obj;
56 }
57
58 X509_REQ *
59 GetX509ReqPtr(VALUE obj)
60 {
61 X509_REQ *req;
62
63 SafeGetX509Req(obj, req);
64
65 return req;
66 }
67
68 X509_REQ *
69 DupX509ReqPtr(VALUE obj)
70 {
71 X509_REQ *req, *new;
72
73 SafeGetX509Req(obj, req);
74 if (!(new = X509_REQ_dup(req))) {
75 ossl_raise(eX509ReqError, NULL);
76 }
77
78 return new;
79 }
80
81 /*
82 * Private functions
83 */
84 static VALUE
85 ossl_x509req_alloc(VALUE klass)
86 {
87 X509_REQ *req;
88 VALUE obj;
89
90 if (!(req = X509_REQ_new())) {
91 ossl_raise(eX509ReqError, NULL);
92 }
93 WrapX509Req(klass, obj, req);
94
95 return obj;
96 }
97
98 static VALUE
99 ossl_x509req_initialize(int argc, VALUE *argv, VALUE self)
100 {
101 BIO *in;
102 X509_REQ *req, *x = DATA_PTR(self);
103 VALUE arg;
104
105 if (rb_scan_args(argc, argv, "01", &arg) == 0) {
106 return self;
107 }
108 arg = ossl_to_der_if_possible(arg);
109 in = ossl_obj2bio(arg);
110 req = PEM_read_bio_X509_REQ(in, &x, NULL, NULL);
111 DATA_PTR(self) = x;
112 if (!req) {
113 OSSL_BIO_reset(in);
114 req = d2i_X509_REQ_bio(in, &x);
115 DATA_PTR(self) = x;
116 }
117 BIO_free(in);
118 if (!req) ossl_raise(eX509ReqError, NULL);
119
120 return self;
121 }
122
123 static VALUE
124 ossl_x509req_copy(VALUE self, VALUE other)
125 {
126 X509_REQ *a, *b, *req;
127
128 rb_check_frozen(self);
129 if (self == other) return self;
130 GetX509Req(self, a);
131 SafeGetX509Req(other, b);
132 if (!(req = X509_REQ_dup(b))) {
133 ossl_raise(eX509ReqError, NULL);
134 }
135 X509_REQ_free(a);
136 DATA_PTR(self) = req;
137
138 return self;
139 }
140
141 static VALUE
142 ossl_x509req_to_pem(VALUE self)
143 {
144 X509_REQ *req;
145 BIO *out;
146 BUF_MEM *buf;
147 VALUE str;
148
149 GetX509Req(self, req);
150 if (!(out = BIO_new(BIO_s_mem()))) {
151 ossl_raise(eX509ReqError, NULL);
152 }
153 if (!PEM_write_bio_X509_REQ(out, req)) {
154 BIO_free(out);
155 ossl_raise(eX509ReqError, NULL);
156 }
157 BIO_get_mem_ptr(out, &buf);
158 str = rb_str_new(buf->data, buf->length);
159 BIO_free(out);
160
161 return str;
162 }
163
164 static VALUE
165 ossl_x509req_to_der(VALUE self)
166 {
167 X509_REQ *req;
168 VALUE str;
169 long len;
170 unsigned char *p;
171
172 GetX509Req(self, req);
173 if ((len = i2d_X509_REQ(req, NULL)) <= 0)
174 ossl_raise(eX509ReqError, NULL);
175 str = rb_str_new(0, len);
176 p = (unsigned char *)RSTRING_PTR(str);
177 if (i2d_X509_REQ(req, &p) <= 0)
178 ossl_raise(eX509ReqError, NULL);
179 ossl_str_adjust(str, p);
180
181 return str;
182 }
183
184 static VALUE
185 ossl_x509req_to_text(VALUE self)
186 {
187 X509_REQ *req;
188 BIO *out;
189 BUF_MEM *buf;
190 VALUE str;
191
192 GetX509Req(self, req);
193 if (!(out = BIO_new(BIO_s_mem()))) {
194 ossl_raise(eX509ReqError, NULL);
195 }
196 if (!X509_REQ_print(out, req)) {
197 BIO_free(out);
198 ossl_raise(eX509ReqError, NULL);
199 }
200 BIO_get_mem_ptr(out, &buf);
201 str = rb_str_new(buf->data, buf->length);
202 BIO_free(out);
203
204 return str;
205 }
206
207 #if 0
208 /*
209 * Makes X509 from X509_REQuest
210 */
211 static VALUE
212 ossl_x509req_to_x509(VALUE self, VALUE days, VALUE key)
213 {
214 X509_REQ *req;
215 X509 *x509;
216
217 GetX509Req(self, req);
218 ...
219 if (!(x509 = X509_REQ_to_X509(req, d, pkey))) {
220 ossl_raise(eX509ReqError, NULL);
221 }
222
223 return ossl_x509_new(x509);
224 }
225 #endif
226
227 static VALUE
228 ossl_x509req_get_version(VALUE self)
229 {
230 X509_REQ *req;
231 long version;
232
233 GetX509Req(self, req);
234 version = X509_REQ_get_version(req);
235
236 return LONG2FIX(version);
237 }
238
239 static VALUE
240 ossl_x509req_set_version(VALUE self, VALUE version)
241 {
242 X509_REQ *req;
243 long ver;
244
245 if ((ver = FIX2LONG(version)) < 0) {
246 ossl_raise(eX509ReqError, "version must be >= 0!");
247 }
248 GetX509Req(self, req);
249 if (!X509_REQ_set_version(req, ver)) {
250 ossl_raise(eX509ReqError, NULL);
251 }
252
253 return version;
254 }
255
256 static VALUE
257 ossl_x509req_get_subject(VALUE self)
258 {
259 X509_REQ *req;
260 X509_NAME *name;
261
262 GetX509Req(self, req);
263 if (!(name = X509_REQ_get_subject_name(req))) { /* NO DUP - don't free */
264 ossl_raise(eX509ReqError, NULL);
265 }
266
267 return ossl_x509name_new(name);
268 }
269
270 static VALUE
271 ossl_x509req_set_subject(VALUE self, VALUE subject)
272 {
273 X509_REQ *req;
274
275 GetX509Req(self, req);
276 /* DUPs name */
277 if (!X509_REQ_set_subject_name(req, GetX509NamePtr(subject))) {
278 ossl_raise(eX509ReqError, NULL);
279 }
280
281 return subject;
282 }
283
284 static VALUE
285 ossl_x509req_get_signature_algorithm(VALUE self)
286 {
287 X509_REQ *req;
288 BIO *out;
289 BUF_MEM *buf;
290 VALUE str;
291
292 GetX509Req(self, req);
293
294 if (!(out = BIO_new(BIO_s_mem()))) {
295 ossl_raise(eX509ReqError, NULL);
296 }
297 if (!i2a_ASN1_OBJECT(out, req->sig_alg->algorithm)) {
298 BIO_free(out);
299 ossl_raise(eX509ReqError, NULL);
300 }
301 BIO_get_mem_ptr(out, &buf);
302 str = rb_str_new(buf->data, buf->length);
303 BIO_free(out);
304 return str;
305 }
306
307 static VALUE
308 ossl_x509req_get_public_key(VALUE self)
309 {
310 X509_REQ *req;
311 EVP_PKEY *pkey;
312
313 GetX509Req(self, req);
314 if (!(pkey = X509_REQ_get_pubkey(req))) { /* adds reference */
315 ossl_raise(eX509ReqError, NULL);
316 }
317
318 return ossl_pkey_new(pkey); /* NO DUP - OK */
319 }
320
321 static VALUE
322 ossl_x509req_set_public_key(VALUE self, VALUE key)
323 {
324 X509_REQ *req;
325 EVP_PKEY *pkey;
326
327 GetX509Req(self, req);
328 pkey = GetPKeyPtr(key); /* NO NEED TO DUP */
329 if (!X509_REQ_set_pubkey(req, pkey)) {
330 ossl_raise(eX509ReqError, NULL);
331 }
332
333 return key;
334 }
335
336 static VALUE
337 ossl_x509req_sign(VALUE self, VALUE key, VALUE digest)
338 {
339 X509_REQ *req;
340 EVP_PKEY *pkey;
341 const EVP_MD *md;
342
343 GetX509Req(self, req);
344 pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */
345 md = GetDigestPtr(digest);
346 if (!X509_REQ_sign(req, pkey, md)) {
347 ossl_raise(eX509ReqError, NULL);
348 }
349
350 return self;
351 }
352
353 /*
354 * Checks that cert signature is made with PRIVversion of this PUBLIC 'key'
355 */
356 static VALUE
357 ossl_x509req_verify(VALUE self, VALUE key)
358 {
359 X509_REQ *req;
360 EVP_PKEY *pkey;
361 int i;
362
363 GetX509Req(self, req);
364 pkey = GetPKeyPtr(key); /* NO NEED TO DUP */
365 if ((i = X509_REQ_verify(req, pkey)) < 0) {
366 ossl_raise(eX509ReqError, NULL);
367 }
368 if (i > 0) {
369 return Qtrue;
370 }
371
372 return Qfalse;
373 }
374
375 static VALUE
376 ossl_x509req_get_attributes(VALUE self)
377 {
378 X509_REQ *req;
379 int count, i;
380 X509_ATTRIBUTE *attr;
381 VALUE ary;
382
383 GetX509Req(self, req);
384
385 count = X509_REQ_get_attr_count(req);
386 if (count < 0) {
387 OSSL_Debug("count < 0???");
388 return rb_ary_new();
389 }
390 ary = rb_ary_new2(count);
391 for (i=0; i<count; i++) {
392 attr = X509_REQ_get_attr(req, i);
393 rb_ary_push(ary, ossl_x509attr_new(attr));
394 }
395
396 return ary;
397 }
398
399 static VALUE
400 ossl_x509req_set_attributes(VALUE self, VALUE ary)
401 {
402 X509_REQ *req;
403 X509_ATTRIBUTE *attr;
404 int i;
405 VALUE item;
406
407 Check_Type(ary, T_ARRAY);
408 for (i=0;i<RARRAY_LEN(ary); i++) {
409 OSSL_Check_Kind(RARRAY_PTR(ary)[i], cX509Attr);
410 }
411 GetX509Req(self, req);
412 sk_X509_ATTRIBUTE_pop_free(req->req_info->attributes, X509_ATTRIBUTE_free);
413 req->req_info->attributes = NULL;
414 for (i=0;i<RARRAY_LEN(ary); i++) {
415 item = RARRAY_PTR(ary)[i];
416 attr = DupX509AttrPtr(item);
417 if (!X509_REQ_add1_attr(req, attr)) {
418 ossl_raise(eX509ReqError, NULL);
419 }
420 }
421 return ary;
422 }
423
424 static VALUE
425 ossl_x509req_add_attribute(VALUE self, VALUE attr)
426 {
427 X509_REQ *req;
428
429 GetX509Req(self, req);
430 if (!X509_REQ_add1_attr(req, DupX509AttrPtr(attr))) {
431 ossl_raise(eX509ReqError, NULL);
432 }
433
434 return attr;
435 }
436
437 /*
438 * X509_REQUEST init
439 */
440 void
441 Init_ossl_x509req()
442 {
443 eX509ReqError = rb_define_class_under(mX509, "RequestError", eOSSLError);
444
445 cX509Req = rb_define_class_under(mX509, "Request", rb_cObject);
446
447 rb_define_alloc_func(cX509Req, ossl_x509req_alloc);
448 rb_define_method(cX509Req, "initialize", ossl_x509req_initialize, -1);
449 rb_define_copy_func(cX509Req, ossl_x509req_copy);
450
451 rb_define_method(cX509Req, "to_pem", ossl_x509req_to_pem, 0);
452 rb_define_method(cX509Req, "to_der", ossl_x509req_to_der, 0);
453 rb_define_alias(cX509Req, "to_s", "to_pem");
454 rb_define_method(cX509Req, "to_text", ossl_x509req_to_text, 0);
455 rb_define_method(cX509Req, "version", ossl_x509req_get_version, 0);
456 rb_define_method(cX509Req, "version=", ossl_x509req_set_version, 1);
457 rb_define_method(cX509Req, "subject", ossl_x509req_get_subject, 0);
458 rb_define_method(cX509Req, "subject=", ossl_x509req_set_subject, 1);
459 rb_define_method(cX509Req, "signature_algorithm", ossl_x509req_get_signature_algorithm, 0);
460 rb_define_method(cX509Req, "public_key", ossl_x509req_get_public_key, 0);
461 rb_define_method(cX509Req, "public_key=", ossl_x509req_set_public_key, 1);
462 rb_define_method(cX509Req, "sign", ossl_x509req_sign, 2);
463 rb_define_method(cX509Req, "verify", ossl_x509req_verify, 1);
464 rb_define_method(cX509Req, "attributes", ossl_x509req_get_attributes, 0);
465 rb_define_method(cX509Req, "attributes=", ossl_x509req_set_attributes, 1);
466 rb_define_method(cX509Req, "add_attribute", ossl_x509req_add_attribute, 1);
467 }
468
469