00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "ossl.h"
00012
00013 #define WrapX509(klass, obj, x509) do { \
00014 if (!(x509)) { \
00015 ossl_raise(rb_eRuntimeError, "CERT wasn't initialized!"); \
00016 } \
00017 (obj) = Data_Wrap_Struct((klass), 0, X509_free, (x509)); \
00018 } while (0)
00019 #define GetX509(obj, x509) do { \
00020 Data_Get_Struct((obj), X509, (x509)); \
00021 if (!(x509)) { \
00022 ossl_raise(rb_eRuntimeError, "CERT wasn't initialized!"); \
00023 } \
00024 } while (0)
00025 #define SafeGetX509(obj, x509) do { \
00026 OSSL_Check_Kind((obj), cX509Cert); \
00027 GetX509((obj), (x509)); \
00028 } while (0)
00029
00030
00031
00032
00033 VALUE cX509Cert;
00034 VALUE eX509CertError;
00035
00036
00037
00038
00039 VALUE
00040 ossl_x509_new(X509 *x509)
00041 {
00042 X509 *new;
00043 VALUE obj;
00044
00045 if (!x509) {
00046 new = X509_new();
00047 } else {
00048 new = X509_dup(x509);
00049 }
00050 if (!new) {
00051 ossl_raise(eX509CertError, NULL);
00052 }
00053 WrapX509(cX509Cert, obj, new);
00054
00055 return obj;
00056 }
00057
00058 VALUE
00059 ossl_x509_new_from_file(VALUE filename)
00060 {
00061 X509 *x509;
00062 FILE *fp;
00063 VALUE obj;
00064
00065 SafeStringValue(filename);
00066 if (!(fp = fopen(RSTRING_PTR(filename), "r"))) {
00067 ossl_raise(eX509CertError, "%s", strerror(errno));
00068 }
00069 rb_fd_fix_cloexec(fileno(fp));
00070 x509 = PEM_read_X509(fp, NULL, NULL, NULL);
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082 fclose(fp);
00083 if (!x509) {
00084 ossl_raise(eX509CertError, NULL);
00085 }
00086 WrapX509(cX509Cert, obj, x509);
00087
00088 return obj;
00089 }
00090
00091 X509 *
00092 GetX509CertPtr(VALUE obj)
00093 {
00094 X509 *x509;
00095
00096 SafeGetX509(obj, x509);
00097
00098 return x509;
00099 }
00100
00101 X509 *
00102 DupX509CertPtr(VALUE obj)
00103 {
00104 X509 *x509;
00105
00106 SafeGetX509(obj, x509);
00107
00108 CRYPTO_add(&x509->references, 1, CRYPTO_LOCK_X509);
00109
00110 return x509;
00111 }
00112
00113
00114
00115
00116 static VALUE
00117 ossl_x509_alloc(VALUE klass)
00118 {
00119 X509 *x509;
00120 VALUE obj;
00121
00122 x509 = X509_new();
00123 if (!x509) ossl_raise(eX509CertError, NULL);
00124
00125 WrapX509(klass, obj, x509);
00126
00127 return obj;
00128 }
00129
00130
00131
00132
00133
00134
00135 static VALUE
00136 ossl_x509_initialize(int argc, VALUE *argv, VALUE self)
00137 {
00138 BIO *in;
00139 X509 *x509, *x = DATA_PTR(self);
00140 VALUE arg;
00141
00142 if (rb_scan_args(argc, argv, "01", &arg) == 0) {
00143
00144 return self;
00145 }
00146 arg = ossl_to_der_if_possible(arg);
00147 in = ossl_obj2bio(arg);
00148 x509 = PEM_read_bio_X509(in, &x, NULL, NULL);
00149 DATA_PTR(self) = x;
00150 if (!x509) {
00151 OSSL_BIO_reset(in);
00152 x509 = d2i_X509_bio(in, &x);
00153 DATA_PTR(self) = x;
00154 }
00155 BIO_free(in);
00156 if (!x509) ossl_raise(eX509CertError, NULL);
00157
00158 return self;
00159 }
00160
00161 static VALUE
00162 ossl_x509_copy(VALUE self, VALUE other)
00163 {
00164 X509 *a, *b, *x509;
00165
00166 rb_check_frozen(self);
00167 if (self == other) return self;
00168
00169 GetX509(self, a);
00170 SafeGetX509(other, b);
00171
00172 x509 = X509_dup(b);
00173 if (!x509) ossl_raise(eX509CertError, NULL);
00174
00175 DATA_PTR(self) = x509;
00176 X509_free(a);
00177
00178 return self;
00179 }
00180
00181
00182
00183
00184
00185 static VALUE
00186 ossl_x509_to_der(VALUE self)
00187 {
00188 X509 *x509;
00189 VALUE str;
00190 long len;
00191 unsigned char *p;
00192
00193 GetX509(self, x509);
00194 if ((len = i2d_X509(x509, NULL)) <= 0)
00195 ossl_raise(eX509CertError, NULL);
00196 str = rb_str_new(0, len);
00197 p = (unsigned char *)RSTRING_PTR(str);
00198 if (i2d_X509(x509, &p) <= 0)
00199 ossl_raise(eX509CertError, NULL);
00200 ossl_str_adjust(str, p);
00201
00202 return str;
00203 }
00204
00205
00206
00207
00208
00209 static VALUE
00210 ossl_x509_to_pem(VALUE self)
00211 {
00212 X509 *x509;
00213 BIO *out;
00214 VALUE str;
00215
00216 GetX509(self, x509);
00217 out = BIO_new(BIO_s_mem());
00218 if (!out) ossl_raise(eX509CertError, NULL);
00219
00220 if (!PEM_write_bio_X509(out, x509)) {
00221 BIO_free(out);
00222 ossl_raise(eX509CertError, NULL);
00223 }
00224 str = ossl_membio2str(out);
00225
00226 return str;
00227 }
00228
00229
00230
00231
00232
00233 static VALUE
00234 ossl_x509_to_text(VALUE self)
00235 {
00236 X509 *x509;
00237 BIO *out;
00238 VALUE str;
00239
00240 GetX509(self, x509);
00241
00242 out = BIO_new(BIO_s_mem());
00243 if (!out) ossl_raise(eX509CertError, NULL);
00244
00245 if (!X509_print(out, x509)) {
00246 BIO_free(out);
00247 ossl_raise(eX509CertError, NULL);
00248 }
00249 str = ossl_membio2str(out);
00250
00251 return str;
00252 }
00253
00254 #if 0
00255
00256
00257
00258 static VALUE
00259 ossl_x509_to_req(VALUE self)
00260 {
00261 X509 *x509;
00262 X509_REQ *req;
00263 VALUE obj;
00264
00265 GetX509(self, x509);
00266 if (!(req = X509_to_X509_REQ(x509, NULL, EVP_md5()))) {
00267 ossl_raise(eX509CertError, NULL);
00268 }
00269 obj = ossl_x509req_new(req);
00270 X509_REQ_free(req);
00271
00272 return obj;
00273 }
00274 #endif
00275
00276
00277
00278
00279
00280 static VALUE
00281 ossl_x509_get_version(VALUE self)
00282 {
00283 X509 *x509;
00284
00285 GetX509(self, x509);
00286
00287 return LONG2NUM(X509_get_version(x509));
00288 }
00289
00290
00291
00292
00293
00294 static VALUE
00295 ossl_x509_set_version(VALUE self, VALUE version)
00296 {
00297 X509 *x509;
00298 long ver;
00299
00300 if ((ver = NUM2LONG(version)) < 0) {
00301 ossl_raise(eX509CertError, "version must be >= 0!");
00302 }
00303 GetX509(self, x509);
00304 if (!X509_set_version(x509, ver)) {
00305 ossl_raise(eX509CertError, NULL);
00306 }
00307
00308 return version;
00309 }
00310
00311
00312
00313
00314
00315 static VALUE
00316 ossl_x509_get_serial(VALUE self)
00317 {
00318 X509 *x509;
00319
00320 GetX509(self, x509);
00321
00322 return asn1integer_to_num(X509_get_serialNumber(x509));
00323 }
00324
00325
00326
00327
00328
00329 static VALUE
00330 ossl_x509_set_serial(VALUE self, VALUE num)
00331 {
00332 X509 *x509;
00333
00334 GetX509(self, x509);
00335
00336 x509->cert_info->serialNumber =
00337 num_to_asn1integer(num, X509_get_serialNumber(x509));
00338
00339 return num;
00340 }
00341
00342
00343
00344
00345
00346 static VALUE
00347 ossl_x509_get_signature_algorithm(VALUE self)
00348 {
00349 X509 *x509;
00350 BIO *out;
00351 VALUE str;
00352
00353 GetX509(self, x509);
00354 out = BIO_new(BIO_s_mem());
00355 if (!out) ossl_raise(eX509CertError, NULL);
00356
00357 if (!i2a_ASN1_OBJECT(out, x509->cert_info->signature->algorithm)) {
00358 BIO_free(out);
00359 ossl_raise(eX509CertError, NULL);
00360 }
00361 str = ossl_membio2str(out);
00362
00363 return str;
00364 }
00365
00366
00367
00368
00369
00370 static VALUE
00371 ossl_x509_get_subject(VALUE self)
00372 {
00373 X509 *x509;
00374 X509_NAME *name;
00375
00376 GetX509(self, x509);
00377 if (!(name = X509_get_subject_name(x509))) {
00378 ossl_raise(eX509CertError, NULL);
00379 }
00380
00381 return ossl_x509name_new(name);
00382 }
00383
00384
00385
00386
00387
00388 static VALUE
00389 ossl_x509_set_subject(VALUE self, VALUE subject)
00390 {
00391 X509 *x509;
00392
00393 GetX509(self, x509);
00394 if (!X509_set_subject_name(x509, GetX509NamePtr(subject))) {
00395 ossl_raise(eX509CertError, NULL);
00396 }
00397
00398 return subject;
00399 }
00400
00401
00402
00403
00404
00405 static VALUE
00406 ossl_x509_get_issuer(VALUE self)
00407 {
00408 X509 *x509;
00409 X509_NAME *name;
00410
00411 GetX509(self, x509);
00412 if(!(name = X509_get_issuer_name(x509))) {
00413 ossl_raise(eX509CertError, NULL);
00414 }
00415
00416 return ossl_x509name_new(name);
00417 }
00418
00419
00420
00421
00422
00423 static VALUE
00424 ossl_x509_set_issuer(VALUE self, VALUE issuer)
00425 {
00426 X509 *x509;
00427
00428 GetX509(self, x509);
00429 if (!X509_set_issuer_name(x509, GetX509NamePtr(issuer))) {
00430 ossl_raise(eX509CertError, NULL);
00431 }
00432
00433 return issuer;
00434 }
00435
00436
00437
00438
00439
00440 static VALUE
00441 ossl_x509_get_not_before(VALUE self)
00442 {
00443 X509 *x509;
00444 ASN1_UTCTIME *asn1time;
00445
00446 GetX509(self, x509);
00447 if (!(asn1time = X509_get_notBefore(x509))) {
00448 ossl_raise(eX509CertError, NULL);
00449 }
00450
00451 return asn1time_to_time(asn1time);
00452 }
00453
00454
00455
00456
00457
00458 static VALUE
00459 ossl_x509_set_not_before(VALUE self, VALUE time)
00460 {
00461 X509 *x509;
00462 time_t sec;
00463
00464 sec = time_to_time_t(time);
00465 GetX509(self, x509);
00466 if (!X509_time_adj(X509_get_notBefore(x509), 0, &sec)) {
00467 ossl_raise(eX509CertError, NULL);
00468 }
00469
00470 return time;
00471 }
00472
00473
00474
00475
00476
00477 static VALUE
00478 ossl_x509_get_not_after(VALUE self)
00479 {
00480 X509 *x509;
00481 ASN1_TIME *asn1time;
00482
00483 GetX509(self, x509);
00484 if (!(asn1time = X509_get_notAfter(x509))) {
00485 ossl_raise(eX509CertError, NULL);
00486 }
00487
00488 return asn1time_to_time(asn1time);
00489 }
00490
00491
00492
00493
00494
00495 static VALUE
00496 ossl_x509_set_not_after(VALUE self, VALUE time)
00497 {
00498 X509 *x509;
00499 time_t sec;
00500
00501 sec = time_to_time_t(time);
00502 GetX509(self, x509);
00503 if (!X509_time_adj(X509_get_notAfter(x509), 0, &sec)) {
00504 ossl_raise(eX509CertError, NULL);
00505 }
00506
00507 return time;
00508 }
00509
00510
00511
00512
00513
00514 static VALUE
00515 ossl_x509_get_public_key(VALUE self)
00516 {
00517 X509 *x509;
00518 EVP_PKEY *pkey;
00519
00520 GetX509(self, x509);
00521 if (!(pkey = X509_get_pubkey(x509))) {
00522 ossl_raise(eX509CertError, NULL);
00523 }
00524
00525 return ossl_pkey_new(pkey);
00526 }
00527
00528
00529
00530
00531
00532 static VALUE
00533 ossl_x509_set_public_key(VALUE self, VALUE key)
00534 {
00535 X509 *x509;
00536
00537 GetX509(self, x509);
00538 if (!X509_set_pubkey(x509, GetPKeyPtr(key))) {
00539 ossl_raise(eX509CertError, NULL);
00540 }
00541
00542 return key;
00543 }
00544
00545
00546
00547
00548
00549 static VALUE
00550 ossl_x509_sign(VALUE self, VALUE key, VALUE digest)
00551 {
00552 X509 *x509;
00553 EVP_PKEY *pkey;
00554 const EVP_MD *md;
00555
00556 pkey = GetPrivPKeyPtr(key);
00557 md = GetDigestPtr(digest);
00558 GetX509(self, x509);
00559 if (!X509_sign(x509, pkey, md)) {
00560 ossl_raise(eX509CertError, NULL);
00561 }
00562
00563 return self;
00564 }
00565
00566
00567
00568
00569
00570
00571
00572 static VALUE
00573 ossl_x509_verify(VALUE self, VALUE key)
00574 {
00575 X509 *x509;
00576 EVP_PKEY *pkey;
00577 int i;
00578
00579 pkey = GetPKeyPtr(key);
00580 GetX509(self, x509);
00581 if ((i = X509_verify(x509, pkey)) < 0) {
00582 ossl_raise(eX509CertError, NULL);
00583 }
00584 if (i > 0) {
00585 return Qtrue;
00586 }
00587
00588 return Qfalse;
00589 }
00590
00591
00592
00593
00594
00595
00596
00597 static VALUE
00598 ossl_x509_check_private_key(VALUE self, VALUE key)
00599 {
00600 X509 *x509;
00601 EVP_PKEY *pkey;
00602
00603
00604 pkey = GetPrivPKeyPtr(key);
00605 GetX509(self, x509);
00606 if (!X509_check_private_key(x509, pkey)) {
00607 OSSL_Warning("Check private key:%s", OSSL_ErrMsg());
00608 return Qfalse;
00609 }
00610
00611 return Qtrue;
00612 }
00613
00614
00615
00616
00617
00618 static VALUE
00619 ossl_x509_get_extensions(VALUE self)
00620 {
00621 X509 *x509;
00622 int count, i;
00623 X509_EXTENSION *ext;
00624 VALUE ary;
00625
00626 GetX509(self, x509);
00627 count = X509_get_ext_count(x509);
00628 if (count < 0) {
00629 return rb_ary_new();
00630 }
00631 ary = rb_ary_new2(count);
00632 for (i=0; i<count; i++) {
00633 ext = X509_get_ext(x509, i);
00634 rb_ary_push(ary, ossl_x509ext_new(ext));
00635 }
00636
00637 return ary;
00638 }
00639
00640
00641
00642
00643
00644 static VALUE
00645 ossl_x509_set_extensions(VALUE self, VALUE ary)
00646 {
00647 X509 *x509;
00648 X509_EXTENSION *ext;
00649 int i;
00650
00651 Check_Type(ary, T_ARRAY);
00652
00653 for (i=0; i<RARRAY_LEN(ary); i++) {
00654 OSSL_Check_Kind(RARRAY_PTR(ary)[i], cX509Ext);
00655 }
00656 GetX509(self, x509);
00657 sk_X509_EXTENSION_pop_free(x509->cert_info->extensions, X509_EXTENSION_free);
00658 x509->cert_info->extensions = NULL;
00659 for (i=0; i<RARRAY_LEN(ary); i++) {
00660 ext = DupX509ExtPtr(RARRAY_PTR(ary)[i]);
00661
00662 if (!X509_add_ext(x509, ext, -1)) {
00663 X509_EXTENSION_free(ext);
00664 ossl_raise(eX509CertError, NULL);
00665 }
00666 X509_EXTENSION_free(ext);
00667 }
00668
00669 return ary;
00670 }
00671
00672
00673
00674
00675
00676 static VALUE
00677 ossl_x509_add_extension(VALUE self, VALUE extension)
00678 {
00679 X509 *x509;
00680 X509_EXTENSION *ext;
00681
00682 GetX509(self, x509);
00683 ext = DupX509ExtPtr(extension);
00684 if (!X509_add_ext(x509, ext, -1)) {
00685 X509_EXTENSION_free(ext);
00686 ossl_raise(eX509CertError, NULL);
00687 }
00688 X509_EXTENSION_free(ext);
00689
00690 return extension;
00691 }
00692
00693 static VALUE
00694 ossl_x509_inspect(VALUE self)
00695 {
00696 return rb_sprintf("#<%"PRIsVALUE": subject=%+"PRIsVALUE", "
00697 "issuer=%+"PRIsVALUE", serial=%+"PRIsVALUE", "
00698 "not_before=%+"PRIsVALUE", not_after=%+"PRIsVALUE">",
00699 rb_obj_class(self),
00700 ossl_x509_get_subject(self),
00701 ossl_x509_get_issuer(self),
00702 ossl_x509_get_serial(self),
00703 ossl_x509_get_not_before(self),
00704 ossl_x509_get_not_after(self));
00705 }
00706
00707
00708
00709
00710 void
00711 Init_ossl_x509cert()
00712 {
00713
00714 #if 0
00715 mOSSL = rb_define_module("OpenSSL");
00716 mX509 = rb_define_module_under(mOSSL, "X509");
00717 #endif
00718
00719 eX509CertError = rb_define_class_under(mX509, "CertificateError", eOSSLError);
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
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813 cX509Cert = rb_define_class_under(mX509, "Certificate", rb_cObject);
00814
00815 rb_define_alloc_func(cX509Cert, ossl_x509_alloc);
00816 rb_define_method(cX509Cert, "initialize", ossl_x509_initialize, -1);
00817 rb_define_copy_func(cX509Cert, ossl_x509_copy);
00818
00819 rb_define_method(cX509Cert, "to_der", ossl_x509_to_der, 0);
00820 rb_define_method(cX509Cert, "to_pem", ossl_x509_to_pem, 0);
00821 rb_define_alias(cX509Cert, "to_s", "to_pem");
00822 rb_define_method(cX509Cert, "to_text", ossl_x509_to_text, 0);
00823 rb_define_method(cX509Cert, "version", ossl_x509_get_version, 0);
00824 rb_define_method(cX509Cert, "version=", ossl_x509_set_version, 1);
00825 rb_define_method(cX509Cert, "signature_algorithm", ossl_x509_get_signature_algorithm, 0);
00826 rb_define_method(cX509Cert, "serial", ossl_x509_get_serial, 0);
00827 rb_define_method(cX509Cert, "serial=", ossl_x509_set_serial, 1);
00828 rb_define_method(cX509Cert, "subject", ossl_x509_get_subject, 0);
00829 rb_define_method(cX509Cert, "subject=", ossl_x509_set_subject, 1);
00830 rb_define_method(cX509Cert, "issuer", ossl_x509_get_issuer, 0);
00831 rb_define_method(cX509Cert, "issuer=", ossl_x509_set_issuer, 1);
00832 rb_define_method(cX509Cert, "not_before", ossl_x509_get_not_before, 0);
00833 rb_define_method(cX509Cert, "not_before=", ossl_x509_set_not_before, 1);
00834 rb_define_method(cX509Cert, "not_after", ossl_x509_get_not_after, 0);
00835 rb_define_method(cX509Cert, "not_after=", ossl_x509_set_not_after, 1);
00836 rb_define_method(cX509Cert, "public_key", ossl_x509_get_public_key, 0);
00837 rb_define_method(cX509Cert, "public_key=", ossl_x509_set_public_key, 1);
00838 rb_define_method(cX509Cert, "sign", ossl_x509_sign, 2);
00839 rb_define_method(cX509Cert, "verify", ossl_x509_verify, 1);
00840 rb_define_method(cX509Cert, "check_private_key", ossl_x509_check_private_key, 1);
00841 rb_define_method(cX509Cert, "extensions", ossl_x509_get_extensions, 0);
00842 rb_define_method(cX509Cert, "extensions=", ossl_x509_set_extensions, 1);
00843 rb_define_method(cX509Cert, "add_extension", ossl_x509_add_extension, 1);
00844 rb_define_method(cX509Cert, "inspect", ossl_x509_inspect, 0);
00845 }
00846
00847