|
Ruby 1.9.2p290(2011-07-09revision32553)
|
00001 /* 00002 * $Id: ossl_x509cert.c 27440 2010-04-22 08:21:01Z nobu $ 00003 * 'OpenSSL for Ruby' project 00004 * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz> 00005 * All rights reserved. 00006 */ 00007 /* 00008 * This program is licenced under the same licence as Ruby. 00009 * (See the file 'LICENCE'.) 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 * Classes 00032 */ 00033 VALUE cX509Cert; 00034 VALUE eX509CertError; 00035 00036 /* 00037 * Public 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 * prepare for DER... 00072 #if !defined(OPENSSL_NO_FP_API) 00073 if (!x509) { 00074 rewind(fp); 00075 00076 x509 = d2i_X509_fp(fp, NULL); 00077 } 00078 #endif 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 * Private 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 * call-seq: 00130 * Certificate.new => cert 00131 * Certificate.new(string) => cert 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 /* create just empty X509Cert */ 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 * call-seq: 00181 * cert.to_der => string 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 * call-seq: 00205 * cert.to_pem => string 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 * call-seq: 00229 * cert.to_text => string 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 * Makes from X509 X509_REQuest 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 * call-seq: 00276 * cert.version => integer 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 * call-seq: 00290 * cert.version = integer => integer 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 * call-seq: 00311 * cert.serial => integer 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 * call-seq: 00325 * cert.serial = integer => integer 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 * call-seq: 00342 * cert.signature_algorithm => string 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 * call-seq: 00366 * cert.subject => name 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))) { /* NO DUP - don't free! */ 00376 ossl_raise(eX509CertError, NULL); 00377 } 00378 00379 return ossl_x509name_new(name); 00380 } 00381 00382 /* 00383 * call-seq: 00384 * cert.subject = name => name 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))) { /* DUPs name */ 00393 ossl_raise(eX509CertError, NULL); 00394 } 00395 00396 return subject; 00397 } 00398 00399 /* 00400 * call-seq: 00401 * cert.issuer => name 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))) { /* NO DUP - don't free! */ 00411 ossl_raise(eX509CertError, NULL); 00412 } 00413 00414 return ossl_x509name_new(name); 00415 } 00416 00417 /* 00418 * call-seq: 00419 * cert.issuer = name => name 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))) { /* DUPs name */ 00428 ossl_raise(eX509CertError, NULL); 00429 } 00430 00431 return issuer; 00432 } 00433 00434 /* 00435 * call-seq: 00436 * cert.not_before => time 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))) { /* NO DUP - don't free! */ 00446 ossl_raise(eX509CertError, NULL); 00447 } 00448 00449 return asn1time_to_time(asn1time); 00450 } 00451 00452 /* 00453 * call-seq: 00454 * cert.not_before = time => time 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 * call-seq: 00473 * cert.not_after => time 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))) { /* NO DUP - don't free! */ 00483 ossl_raise(eX509CertError, NULL); 00484 } 00485 00486 return asn1time_to_time(asn1time); 00487 } 00488 00489 /* 00490 * call-seq: 00491 * cert.not_before = time => time 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 * call-seq: 00510 * cert.public_key => key 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))) { /* adds an reference */ 00520 ossl_raise(eX509CertError, NULL); 00521 } 00522 00523 return ossl_pkey_new(pkey); /* NO DUP - OK */ 00524 } 00525 00526 /* 00527 * call-seq: 00528 * cert.public_key = key => key 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))) { /* DUPs pkey */ 00537 ossl_raise(eX509CertError, NULL); 00538 } 00539 00540 return key; 00541 } 00542 00543 /* 00544 * call-seq: 00545 * cert.sign(key, digest) => self 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); /* NO NEED TO DUP */ 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 * call-seq: 00566 * cert.verify(key) => true | false 00567 * 00568 * Checks that cert signature is made with PRIVversion of this PUBLIC 'key' 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); /* NO NEED TO DUP */ 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 * call-seq: 00591 * cert.check_private_key(key) 00592 * 00593 * Checks if 'key' is PRIV key for this cert 00594 */ 00595 static VALUE 00596 ossl_x509_check_private_key(VALUE self, VALUE key) 00597 { 00598 X509 *x509; 00599 EVP_PKEY *pkey; 00600 00601 /* not needed private key, but should be */ 00602 pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */ 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 * call-seq: 00614 * cert.extensions => [extension...] 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); /* NO DUP - don't free! */ 00632 rb_ary_push(ary, ossl_x509ext_new(ext)); 00633 } 00634 00635 return ary; 00636 } 00637 00638 /* 00639 * call-seq: 00640 * cert.extensions = [ext...] => [ext...] 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 /* All ary's members should be X509Extension */ 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)) { /* DUPs ext - FREE it */ 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 * call-seq: 00672 * cert.add_extension(extension) => extension 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)) { /* DUPs ext - FREE it */ 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 * INIT 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
1.7.3