Ruby  1.9.3p551(2014-11-13revision48407)
ossl_x509store.c
Go to the documentation of this file.
1 /*
2  * $Id: ossl_x509store.c 31165 2011-03-24 04:49:18Z naruse $
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 WrapX509Store(klass, obj, st) do { \
14  if (!(st)) { \
15  ossl_raise(rb_eRuntimeError, "STORE wasn't initialized!"); \
16  } \
17  (obj) = Data_Wrap_Struct((klass), 0, X509_STORE_free, (st)); \
18 } while (0)
19 #define GetX509Store(obj, st) do { \
20  Data_Get_Struct((obj), X509_STORE, (st)); \
21  if (!(st)) { \
22  ossl_raise(rb_eRuntimeError, "STORE wasn't initialized!"); \
23  } \
24 } while (0)
25 #define SafeGetX509Store(obj, st) do { \
26  OSSL_Check_Kind((obj), cX509Store); \
27  GetX509Store((obj), (st)); \
28 } while (0)
29 
30 #define WrapX509StCtx(klass, obj, ctx) do { \
31  if (!(ctx)) { \
32  ossl_raise(rb_eRuntimeError, "STORE_CTX wasn't initialized!"); \
33  } \
34  (obj) = Data_Wrap_Struct((klass), 0, ossl_x509stctx_free, (ctx)); \
35 } while (0)
36 #define GetX509StCtx(obj, ctx) do { \
37  Data_Get_Struct((obj), X509_STORE_CTX, (ctx)); \
38  if (!(ctx)) { \
39  ossl_raise(rb_eRuntimeError, "STORE_CTX is out of scope!"); \
40  } \
41 } while (0)
42 #define SafeGetX509StCtx(obj, storep) do { \
43  OSSL_Check_Kind((obj), cX509StoreContext); \
44  GetX509Store((obj), (ctx)); \
45 } while (0)
46 
47 /*
48  * Classes
49  */
53 
54 /*
55  * Public functions
56  */
57 VALUE
58 ossl_x509store_new(X509_STORE *store)
59 {
60  VALUE obj;
61 
62  WrapX509Store(cX509Store, obj, store);
63 
64  return obj;
65 }
66 
67 X509_STORE *
69 {
70  X509_STORE *store;
71 
72  SafeGetX509Store(obj, store);
73 
74  return store;
75 }
76 
77 X509_STORE *
79 {
80  X509_STORE *store;
81 
82  SafeGetX509Store(obj, store);
83  CRYPTO_add(&store->references, 1, CRYPTO_LOCK_X509_STORE);
84 
85  return store;
86 }
87 
88 /*
89  * Private functions
90  */
91 static VALUE
93 {
94  X509_STORE *store;
95  VALUE obj;
96 
97  if((store = X509_STORE_new()) == NULL){
99  }
100  WrapX509Store(klass, obj, store);
101 
102  return obj;
103 }
104 
105 /*
106  * General callback for OpenSSL verify
107  */
108 static VALUE
110 {
111  X509_STORE *store;
112 
113  GetX509Store(self, store);
114  X509_STORE_set_ex_data(store, ossl_verify_cb_idx, (void*)cb);
115  rb_iv_set(self, "@verify_callback", cb);
116 
117  return cb;
118 }
119 
120 
121 /*
122  * call-seq:
123  * X509::Store.new => store
124  *
125  */
126 static VALUE
128 {
129  X509_STORE *store;
130 
131 /* BUG: This method takes any number of arguments but appears to ignore them. */
132  GetX509Store(self, store);
133  store->ex_data.sk = NULL;
134  X509_STORE_set_verify_cb_func(store, ossl_verify_cb);
136 
137 #if (OPENSSL_VERSION_NUMBER < 0x00907000L)
138  rb_iv_set(self, "@flags", INT2NUM(0));
139  rb_iv_set(self, "@purpose", INT2NUM(0));
140  rb_iv_set(self, "@trust", INT2NUM(0));
141 #endif
142 
143  /* last verification status */
144  rb_iv_set(self, "@error", Qnil);
145  rb_iv_set(self, "@error_string", Qnil);
146  rb_iv_set(self, "@chain", Qnil);
147  rb_iv_set(self, "@time", Qnil);
148 
149  return self;
150 }
151 
152 static VALUE
154 {
155 #if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
156  X509_STORE *store;
157  long f = NUM2LONG(flags);
158 
159  GetX509Store(self, store);
160  X509_STORE_set_flags(store, f);
161 #else
162  rb_iv_set(self, "@flags", flags);
163 #endif
164 
165  return flags;
166 }
167 
168 static VALUE
170 {
171 #if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
172  X509_STORE *store;
173  int p = NUM2INT(purpose);
174 
175  GetX509Store(self, store);
176  X509_STORE_set_purpose(store, p);
177 #else
178  rb_iv_set(self, "@purpose", purpose);
179 #endif
180 
181  return purpose;
182 }
183 
184 static VALUE
186 {
187 #if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
188  X509_STORE *store;
189  int t = NUM2INT(trust);
190 
191  GetX509Store(self, store);
192  X509_STORE_set_trust(store, t);
193 #else
194  rb_iv_set(self, "@trust", trust);
195 #endif
196 
197  return trust;
198 }
199 
200 static VALUE
202 {
203  rb_iv_set(self, "@time", time);
204  return time;
205 }
206 
207 static VALUE
209 {
210  X509_STORE *store;
211  X509_LOOKUP *lookup;
212  char *path = NULL;
213 
214  if(file != Qnil){
215  SafeStringValue(file);
216  path = RSTRING_PTR(file);
217  }
218  GetX509Store(self, store);
219  lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
220  if(lookup == NULL) ossl_raise(eX509StoreError, NULL);
221  if(X509_LOOKUP_load_file(lookup, path, X509_FILETYPE_PEM) != 1){
223  }
224 
225  return self;
226 }
227 
228 static VALUE
230 {
231  X509_STORE *store;
232  X509_LOOKUP *lookup;
233  char *path = NULL;
234 
235  if(dir != Qnil){
236  SafeStringValue(dir);
237  path = RSTRING_PTR(dir);
238  }
239  GetX509Store(self, store);
240  lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir());
241  if(lookup == NULL) ossl_raise(eX509StoreError, NULL);
242  if(X509_LOOKUP_add_dir(lookup, path, X509_FILETYPE_PEM) != 1){
244  }
245 
246  return self;
247 }
248 
249 static VALUE
251 {
252  X509_STORE *store;
253 
254  GetX509Store(self, store);
255  if (X509_STORE_set_default_paths(store) != 1){
257  }
258 
259  return Qnil;
260 }
261 
262 static VALUE
264 {
265  X509_STORE *store;
266  X509 *cert;
267 
268  cert = GetX509CertPtr(arg); /* NO NEED TO DUP */
269  GetX509Store(self, store);
270  if (X509_STORE_add_cert(store, cert) != 1){
272  }
273 
274  return self;
275 }
276 
277 static VALUE
279 {
280  X509_STORE *store;
281  X509_CRL *crl;
282 
283  crl = GetX509CRLPtr(arg); /* NO NEED TO DUP */
284  GetX509Store(self, store);
285  if (X509_STORE_add_crl(store, crl) != 1){
287  }
288 
289  return self;
290 }
291 
295 
296 static VALUE
298 {
299  VALUE cert, chain;
300  VALUE ctx, proc, result;
301 
302  rb_scan_args(argc, argv, "11", &cert, &chain);
303  ctx = rb_funcall(cX509StoreContext, rb_intern("new"), 3, self, cert, chain);
304  proc = rb_block_given_p() ? rb_block_proc() :
305  rb_iv_get(self, "@verify_callback");
306  rb_iv_set(ctx, "@verify_callback", proc);
307  result = rb_funcall(ctx, rb_intern("verify"), 0);
308 
309  rb_iv_set(self, "@error", ossl_x509stctx_get_err(ctx));
310  rb_iv_set(self, "@error_string", ossl_x509stctx_get_err_string(ctx));
311  rb_iv_set(self, "@chain", ossl_x509stctx_get_chain(ctx));
312 
313  return result;
314 }
315 
316 /*
317  * Public Functions
318  */
319 static void ossl_x509stctx_free(X509_STORE_CTX*);
320 
321 VALUE
322 ossl_x509stctx_new(X509_STORE_CTX *ctx)
323 {
324  VALUE obj;
325 
326  WrapX509StCtx(cX509StoreContext, obj, ctx);
327 
328  return obj;
329 }
330 
331 VALUE
333 {
335  RDATA(obj)->data = NULL;
336 
337  return obj;
338 }
339 
340 /*
341  * Private functions
342  */
343 static void
344 ossl_x509stctx_free(X509_STORE_CTX *ctx)
345 {
346  if(ctx->untrusted)
347  sk_X509_pop_free(ctx->untrusted, X509_free);
348  if(ctx->cert)
349  X509_free(ctx->cert);
350  X509_STORE_CTX_free(ctx);
351 }
352 
353 static VALUE
355 {
356  X509_STORE_CTX *ctx;
357  VALUE obj;
358 
359  if((ctx = X509_STORE_CTX_new()) == NULL){
361  }
362  WrapX509StCtx(klass, obj, ctx);
363 
364  return obj;
365 }
366 
371 
372 static VALUE
374 {
375  VALUE store, cert, chain, t;
376  X509_STORE_CTX *ctx;
377  X509_STORE *x509st;
378  X509 *x509 = NULL;
379  STACK_OF(X509) *x509s = NULL;
380 
381  rb_scan_args(argc, argv, "12", &store, &cert, &chain);
382  GetX509StCtx(self, ctx);
383  SafeGetX509Store(store, x509st);
384  if(!NIL_P(cert)) x509 = DupX509CertPtr(cert); /* NEED TO DUP */
385  if(!NIL_P(chain)) x509s = ossl_x509_ary2sk(chain);
386 #if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
387  if(X509_STORE_CTX_init(ctx, x509st, x509, x509s) != 1){
388  sk_X509_pop_free(x509s, X509_free);
390  }
391 #else
392  X509_STORE_CTX_init(ctx, x509st, x509, x509s);
393  ossl_x509stctx_set_flags(self, rb_iv_get(store, "@flags"));
394  ossl_x509stctx_set_purpose(self, rb_iv_get(store, "@purpose"));
395  ossl_x509stctx_set_trust(self, rb_iv_get(store, "@trust"));
396 #endif
397  if (!NIL_P(t = rb_iv_get(store, "@time")))
398  ossl_x509stctx_set_time(self, t);
399  rb_iv_set(self, "@verify_callback", rb_iv_get(store, "@verify_callback"));
400  rb_iv_set(self, "@cert", cert);
401 
402  return self;
403 }
404 
405 static VALUE
407 {
408  X509_STORE_CTX *ctx;
409  int result;
410 
411  GetX509StCtx(self, ctx);
412  X509_STORE_CTX_set_ex_data(ctx, ossl_verify_cb_idx,
413  (void*)rb_iv_get(self, "@verify_callback"));
414  result = X509_verify_cert(ctx);
415 
416  return result ? Qtrue : Qfalse;
417 }
418 
419 static VALUE
421 {
422  X509_STORE_CTX *ctx;
423  STACK_OF(X509) *chain;
424  X509 *x509;
425  int i, num;
426  VALUE ary;
427 
428  GetX509StCtx(self, ctx);
429  if((chain = X509_STORE_CTX_get_chain(ctx)) == NULL){
430  return Qnil;
431  }
432  if((num = sk_X509_num(chain)) < 0){
433  OSSL_Debug("certs in chain < 0???");
434  return rb_ary_new();
435  }
436  ary = rb_ary_new2(num);
437  for(i = 0; i < num; i++) {
438  x509 = sk_X509_value(chain, i);
439  rb_ary_push(ary, ossl_x509_new(x509));
440  }
441 
442  return ary;
443 }
444 
445 static VALUE
447 {
448  X509_STORE_CTX *ctx;
449 
450  GetX509StCtx(self, ctx);
451 
452  return INT2FIX(X509_STORE_CTX_get_error(ctx));
453 }
454 
455 static VALUE
457 {
458  X509_STORE_CTX *ctx;
459 
460  GetX509StCtx(self, ctx);
461  X509_STORE_CTX_set_error(ctx, NUM2INT(err));
462 
463  return err;
464 }
465 
466 static VALUE
468 {
469  X509_STORE_CTX *ctx;
470  long err;
471 
472  GetX509StCtx(self, ctx);
473  err = X509_STORE_CTX_get_error(ctx);
474 
475  return rb_str_new2(X509_verify_cert_error_string(err));
476 }
477 
478 static VALUE
480 {
481  X509_STORE_CTX *ctx;
482 
483  GetX509StCtx(self, ctx);
484 
485  return INT2FIX(X509_STORE_CTX_get_error_depth(ctx));
486 }
487 
488 static VALUE
490 {
491  X509_STORE_CTX *ctx;
492 
493  GetX509StCtx(self, ctx);
494 
495  return ossl_x509_new(X509_STORE_CTX_get_current_cert(ctx));
496 }
497 
498 static VALUE
500 {
501 #if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
502  X509_STORE_CTX *ctx;
503 
504  GetX509StCtx(self, ctx);
505  if(!ctx->current_crl) return Qnil;
506 
507  return ossl_x509crl_new(ctx->current_crl);
508 #else
509  return Qnil;
510 #endif
511 }
512 
513 static VALUE
515 {
516  X509_STORE_CTX *store;
517  long f = NUM2LONG(flags);
518 
519  GetX509StCtx(self, store);
520  X509_STORE_CTX_set_flags(store, f);
521 
522  return flags;
523 }
524 
525 static VALUE
527 {
528  X509_STORE_CTX *store;
529  int p = NUM2INT(purpose);
530 
531  GetX509StCtx(self, store);
532  X509_STORE_CTX_set_purpose(store, p);
533 
534  return purpose;
535 }
536 
537 static VALUE
539 {
540  X509_STORE_CTX *store;
541  int t = NUM2INT(trust);
542 
543  GetX509StCtx(self, store);
544  X509_STORE_CTX_set_trust(store, t);
545 
546  return trust;
547 }
548 
549 /*
550  * call-seq:
551  * storectx.time = time => time
552  */
553 static VALUE
555 {
556  X509_STORE_CTX *store;
557  long t;
558 
559  t = NUM2LONG(rb_Integer(time));
560  GetX509StCtx(self, store);
561  X509_STORE_CTX_set_time(store, 0, t);
562 
563  return time;
564 }
565 
566 /*
567  * INIT
568  */
569 void
571 {
572  VALUE x509stctx;
573 
575 
577  rb_attr(cX509Store, rb_intern("verify_callback"), 1, 0, Qfalse);
578  rb_attr(cX509Store, rb_intern("error"), 1, 0, Qfalse);
579  rb_attr(cX509Store, rb_intern("error_string"), 1, 0, Qfalse);
580  rb_attr(cX509Store, rb_intern("chain"), 1, 0, Qfalse);
583  rb_define_method(cX509Store, "verify_callback=", ossl_x509store_set_vfy_cb, 1);
594 
596  x509stctx = cX509StoreContext;
598  rb_define_method(x509stctx,"initialize", ossl_x509stctx_initialize, -1);
599  rb_define_method(x509stctx,"verify", ossl_x509stctx_verify, 0);
600  rb_define_method(x509stctx,"chain", ossl_x509stctx_get_chain,0);
601  rb_define_method(x509stctx,"error", ossl_x509stctx_get_err, 0);
602  rb_define_method(x509stctx,"error=", ossl_x509stctx_set_error, 1);
603  rb_define_method(x509stctx,"error_string",ossl_x509stctx_get_err_string,0);
604  rb_define_method(x509stctx,"error_depth", ossl_x509stctx_get_err_depth, 0);
605  rb_define_method(x509stctx,"current_cert",ossl_x509stctx_get_curr_cert, 0);
606  rb_define_method(x509stctx,"current_crl", ossl_x509stctx_get_curr_crl, 0);
607  rb_define_method(x509stctx,"flags=", ossl_x509stctx_set_flags, 1);
608  rb_define_method(x509stctx,"purpose=", ossl_x509stctx_set_purpose, 1);
609  rb_define_method(x509stctx,"trust=", ossl_x509stctx_set_trust, 1);
610  rb_define_method(x509stctx,"time=", ossl_x509stctx_set_time, 1);
611 
612 }
613