00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "ossl.h"
00012 #include <stdarg.h>
00013
00014
00015
00016
00017 int
00018 string2hex(const unsigned char *buf, int buf_len, char **hexbuf, int *hexbuf_len)
00019 {
00020 static const char hex[]="0123456789abcdef";
00021 int i, len = 2 * buf_len;
00022
00023 if (buf_len < 0 || len < buf_len) {
00024 return -1;
00025 }
00026 if (!hexbuf) {
00027 if (hexbuf_len) {
00028 *hexbuf_len = len;
00029 }
00030 return len;
00031 }
00032 if (!(*hexbuf = OPENSSL_malloc(len + 1))) {
00033 return -1;
00034 }
00035 for (i = 0; i < buf_len; i++) {
00036 (*hexbuf)[2 * i] = hex[((unsigned char)buf[i]) >> 4];
00037 (*hexbuf)[2 * i + 1] = hex[buf[i] & 0x0f];
00038 }
00039 (*hexbuf)[2 * i] = '\0';
00040
00041 if (hexbuf_len) {
00042 *hexbuf_len = len;
00043 }
00044 return len;
00045 }
00046
00047
00048
00049
00050 #define OSSL_IMPL_ARY2SK(name, type, expected_class, dup) \
00051 STACK_OF(type) * \
00052 ossl_##name##_ary2sk0(VALUE ary) \
00053 { \
00054 STACK_OF(type) *sk; \
00055 VALUE val; \
00056 type *x; \
00057 int i; \
00058 \
00059 Check_Type(ary, T_ARRAY); \
00060 sk = sk_##type##_new_null(); \
00061 if (!sk) ossl_raise(eOSSLError, NULL); \
00062 \
00063 for (i = 0; i < RARRAY_LEN(ary); i++) { \
00064 val = rb_ary_entry(ary, i); \
00065 if (!rb_obj_is_kind_of(val, expected_class)) { \
00066 sk_##type##_pop_free(sk, type##_free); \
00067 ossl_raise(eOSSLError, "object in array not" \
00068 " of class ##type##"); \
00069 } \
00070 x = dup(val); \
00071 sk_##type##_push(sk, x); \
00072 } \
00073 return sk; \
00074 } \
00075 \
00076 STACK_OF(type) * \
00077 ossl_protect_##name##_ary2sk(VALUE ary, int *status) \
00078 { \
00079 return (STACK_OF(type)*)rb_protect( \
00080 (VALUE(*)_((VALUE)))ossl_##name##_ary2sk0, \
00081 ary, \
00082 status); \
00083 } \
00084 \
00085 STACK_OF(type) * \
00086 ossl_##name##_ary2sk(VALUE ary) \
00087 { \
00088 STACK_OF(type) *sk; \
00089 int status = 0; \
00090 \
00091 sk = ossl_protect_##name##_ary2sk(ary, &status); \
00092 if (status) rb_jump_tag(status); \
00093 \
00094 return sk; \
00095 }
00096 OSSL_IMPL_ARY2SK(x509, X509, cX509Cert, DupX509CertPtr)
00097
00098 #define OSSL_IMPL_SK2ARY(name, type) \
00099 VALUE \
00100 ossl_##name##_sk2ary(STACK_OF(type) *sk) \
00101 { \
00102 type *t; \
00103 int i, num; \
00104 VALUE ary; \
00105 \
00106 if (!sk) { \
00107 OSSL_Debug("empty sk!"); \
00108 return Qnil; \
00109 } \
00110 num = sk_##type##_num(sk); \
00111 if (num < 0) { \
00112 OSSL_Debug("items in sk < -1???"); \
00113 return rb_ary_new(); \
00114 } \
00115 ary = rb_ary_new2(num); \
00116 \
00117 for (i=0; i<num; i++) { \
00118 t = sk_##type##_value(sk, i); \
00119 rb_ary_push(ary, ossl_##name##_new(t)); \
00120 } \
00121 return ary; \
00122 }
00123 OSSL_IMPL_SK2ARY(x509, X509)
00124 OSSL_IMPL_SK2ARY(x509crl, X509_CRL)
00125 OSSL_IMPL_SK2ARY(x509name, X509_NAME)
00126
00127 static VALUE
00128 ossl_str_new(int size)
00129 {
00130 return rb_str_new(0, size);
00131 }
00132
00133 VALUE
00134 ossl_buf2str(char *buf, int len)
00135 {
00136 VALUE str;
00137 int status = 0;
00138
00139 str = rb_protect((VALUE(*)_((VALUE)))ossl_str_new, len, &status);
00140 if(!NIL_P(str)) memcpy(RSTRING_PTR(str), buf, len);
00141 OPENSSL_free(buf);
00142 if(status) rb_jump_tag(status);
00143
00144 return str;
00145 }
00146
00147
00148
00149
00150 static VALUE
00151 ossl_pem_passwd_cb0(VALUE flag)
00152 {
00153 VALUE pass;
00154
00155 pass = rb_yield(flag);
00156 SafeStringValue(pass);
00157
00158 return pass;
00159 }
00160
00161 int
00162 ossl_pem_passwd_cb(char *buf, int max_len, int flag, void *pwd)
00163 {
00164 int len, status = 0;
00165 VALUE rflag, pass;
00166
00167 if (pwd || !rb_block_given_p())
00168 return PEM_def_callback(buf, max_len, flag, pwd);
00169
00170 while (1) {
00171
00172
00173
00174
00175
00176 rflag = flag ? Qtrue : Qfalse;
00177 pass = rb_protect(ossl_pem_passwd_cb0, rflag, &status);
00178 if (status) return -1;
00179 len = RSTRING_LENINT(pass);
00180 if (len < 4) {
00181 rb_warning("password must be longer than 4 bytes");
00182 continue;
00183 }
00184 if (len > max_len) {
00185 rb_warning("password must be shorter then %d bytes", max_len-1);
00186 continue;
00187 }
00188 memcpy(buf, RSTRING_PTR(pass), len);
00189 break;
00190 }
00191 return len;
00192 }
00193
00194
00195
00196
00197 int ossl_verify_cb_idx;
00198
00199 VALUE
00200 ossl_call_verify_cb_proc(struct ossl_verify_cb_args *args)
00201 {
00202 return rb_funcall(args->proc, rb_intern("call"), 2,
00203 args->preverify_ok, args->store_ctx);
00204 }
00205
00206 int
00207 ossl_verify_cb(int ok, X509_STORE_CTX *ctx)
00208 {
00209 VALUE proc, rctx, ret;
00210 struct ossl_verify_cb_args args;
00211 int state = 0;
00212
00213 proc = (VALUE)X509_STORE_CTX_get_ex_data(ctx, ossl_verify_cb_idx);
00214 if ((void*)proc == 0)
00215 proc = (VALUE)X509_STORE_get_ex_data(ctx->ctx, ossl_verify_cb_idx);
00216 if ((void*)proc == 0)
00217 return ok;
00218 if (!NIL_P(proc)) {
00219 rctx = rb_protect((VALUE(*)(VALUE))ossl_x509stctx_new,
00220 (VALUE)ctx, &state);
00221 ret = Qfalse;
00222 if (!state) {
00223 args.proc = proc;
00224 args.preverify_ok = ok ? Qtrue : Qfalse;
00225 args.store_ctx = rctx;
00226 ret = rb_protect((VALUE(*)(VALUE))ossl_call_verify_cb_proc, (VALUE)&args, &state);
00227 ossl_x509stctx_clear_ptr(rctx);
00228 if (state) {
00229 rb_warn("exception in verify_callback is ignored");
00230 }
00231 }
00232 if (ret == Qtrue) {
00233 X509_STORE_CTX_set_error(ctx, X509_V_OK);
00234 ok = 1;
00235 }
00236 else{
00237 if (X509_STORE_CTX_get_error(ctx) == X509_V_OK) {
00238 X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REJECTED);
00239 }
00240 ok = 0;
00241 }
00242 }
00243
00244 return ok;
00245 }
00246
00247
00248
00249
00250 VALUE mOSSL;
00251
00252
00253
00254
00255 VALUE eOSSLError;
00256
00257
00258
00259
00260 ID ossl_s_to_der;
00261
00262 VALUE
00263 ossl_to_der(VALUE obj)
00264 {
00265 VALUE tmp;
00266
00267 tmp = rb_funcall(obj, ossl_s_to_der, 0);
00268 StringValue(tmp);
00269
00270 return tmp;
00271 }
00272
00273 VALUE
00274 ossl_to_der_if_possible(VALUE obj)
00275 {
00276 if(rb_respond_to(obj, ossl_s_to_der))
00277 return ossl_to_der(obj);
00278 return obj;
00279 }
00280
00281
00282
00283
00284 static VALUE
00285 ossl_make_error(VALUE exc, const char *fmt, va_list args)
00286 {
00287 char buf[BUFSIZ];
00288 const char *msg;
00289 long e;
00290 int len = 0;
00291
00292 #ifdef HAVE_ERR_PEEK_LAST_ERROR
00293 e = ERR_peek_last_error();
00294 #else
00295 e = ERR_peek_error();
00296 #endif
00297 if (fmt) {
00298 len = vsnprintf(buf, BUFSIZ, fmt, args);
00299 }
00300 if (len < BUFSIZ && e) {
00301 if (dOSSL == Qtrue)
00302 msg = ERR_error_string(e, NULL);
00303 else
00304 msg = ERR_reason_error_string(e);
00305 len += snprintf(buf+len, BUFSIZ-len, "%s%s", (len ? ": " : ""), msg);
00306 }
00307 if (dOSSL == Qtrue){
00308 while ((e = ERR_get_error()) != 0){
00309 rb_warn("error on stack: %s", ERR_error_string(e, NULL));
00310 }
00311 }
00312 ERR_clear_error();
00313
00314 if(len > BUFSIZ) len = rb_long2int(strlen(buf));
00315 return rb_exc_new(exc, buf, len);
00316 }
00317
00318 void
00319 ossl_raise(VALUE exc, const char *fmt, ...)
00320 {
00321 va_list args;
00322 VALUE err;
00323 va_start(args, fmt);
00324 err = ossl_make_error(exc, fmt, args);
00325 va_end(args);
00326 rb_exc_raise(err);
00327 }
00328
00329 VALUE
00330 ossl_exc_new(VALUE exc, const char *fmt, ...)
00331 {
00332 va_list args;
00333 VALUE err;
00334 va_start(args, fmt);
00335 err = ossl_make_error(exc, fmt, args);
00336 va_end(args);
00337 return err;
00338 }
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348 VALUE
00349 ossl_get_errors()
00350 {
00351 VALUE ary;
00352 long e;
00353
00354 ary = rb_ary_new();
00355 while ((e = ERR_get_error()) != 0){
00356 rb_ary_push(ary, rb_str_new2(ERR_error_string(e, NULL)));
00357 }
00358
00359 return ary;
00360 }
00361
00362
00363
00364
00365 VALUE dOSSL;
00366
00367 #if !defined(HAVE_VA_ARGS_MACRO)
00368 void
00369 ossl_debug(const char *fmt, ...)
00370 {
00371 va_list args;
00372
00373 if (dOSSL == Qtrue) {
00374 fprintf(stderr, "OSSL_DEBUG: ");
00375 va_start(args, fmt);
00376 vfprintf(stderr, fmt, args);
00377 va_end(args);
00378 fprintf(stderr, " [CONTEXT N/A]\n");
00379 }
00380 }
00381 #endif
00382
00383
00384
00385
00386
00387 static VALUE
00388 ossl_debug_get(VALUE self)
00389 {
00390 return dOSSL;
00391 }
00392
00393
00394
00395
00396
00397
00398
00399
00400 static VALUE
00401 ossl_debug_set(VALUE self, VALUE val)
00402 {
00403 VALUE old = dOSSL;
00404 dOSSL = val;
00405
00406 if (old != dOSSL) {
00407 if (dOSSL == Qtrue) {
00408 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
00409 fprintf(stderr, "OSSL_DEBUG: IS NOW ON!\n");
00410 } else if (old == Qtrue) {
00411 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_OFF);
00412 fprintf(stderr, "OSSL_DEBUG: IS NOW OFF!\n");
00413 }
00414 }
00415 return val;
00416 }
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791 void
00792 Init_openssl()
00793 {
00794
00795
00796
00797 #if 0
00798 tzset();
00799 #endif
00800
00801
00802
00803
00804
00805
00806 OpenSSL_add_ssl_algorithms();
00807 OpenSSL_add_all_algorithms();
00808 ERR_load_crypto_strings();
00809 SSL_load_error_strings();
00810
00811
00812
00813
00814
00815 #if 0
00816 CONF_modules_unload(1);
00817 destroy_ui_method();
00818 EVP_cleanup();
00819 ENGINE_cleanup();
00820 CRYPTO_cleanup_all_ex_data();
00821 ERR_remove_state(0);
00822 ERR_free_strings();
00823 #endif
00824
00825
00826
00827
00828 mOSSL = rb_define_module("OpenSSL");
00829
00830
00831
00832
00833 rb_define_const(mOSSL, "VERSION", rb_str_new2(OSSL_VERSION));
00834
00835
00836
00837
00838 rb_define_const(mOSSL, "OPENSSL_VERSION", rb_str_new2(OPENSSL_VERSION_TEXT));
00839
00840
00841
00842
00843 rb_define_const(mOSSL, "OPENSSL_VERSION_NUMBER", INT2NUM(OPENSSL_VERSION_NUMBER));
00844
00845
00846
00847
00848
00849 eOSSLError = rb_define_class_under(mOSSL,"OpenSSLError",rb_eStandardError);
00850
00851
00852
00853
00854 if ((ossl_verify_cb_idx = X509_STORE_CTX_get_ex_new_index(0, (void *)"ossl_verify_cb_idx", 0, 0, 0)) < 0)
00855 ossl_raise(eOSSLError, "X509_STORE_CTX_get_ex_new_index");
00856
00857
00858
00859
00860 dOSSL = Qfalse;
00861 rb_define_module_function(mOSSL, "debug", ossl_debug_get, 0);
00862 rb_define_module_function(mOSSL, "debug=", ossl_debug_set, 1);
00863 rb_define_module_function(mOSSL, "errors", ossl_get_errors, 0);
00864
00865
00866
00867
00868 ossl_s_to_der = rb_intern("to_der");
00869
00870
00871
00872
00873 Init_ossl_bn();
00874 Init_ossl_cipher();
00875 Init_ossl_config();
00876 Init_ossl_digest();
00877 Init_ossl_hmac();
00878 Init_ossl_ns_spki();
00879 Init_ossl_pkcs12();
00880 Init_ossl_pkcs7();
00881 Init_ossl_pkcs5();
00882 Init_ossl_pkey();
00883 Init_ossl_rand();
00884 Init_ossl_ssl();
00885 Init_ossl_x509();
00886 Init_ossl_ocsp();
00887 Init_ossl_engine();
00888 Init_ossl_asn1();
00889 }
00890
00891 #if defined(OSSL_DEBUG)
00892
00893
00894
00895 int
00896 main(int argc, char *argv[])
00897 {
00898 return 0;
00899 }
00900 #endif
00901
00902