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