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