|
Ruby
1.9.3p537(2014-02-19revision0)
|
00001 /* 00002 * $Id$ 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 #include <stdarg.h> /* for ossl_raise */ 00013 00014 /* 00015 * String to HEXString conversion 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) { /* PARANOIA? */ 00024 return -1; 00025 } 00026 if (!hexbuf) { /* if no buf, return calculated len */ 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 * Data Conversion 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); /* NEED TO DUP */ \ 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 * our default PEM callback 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 * when the flag is nonzero, this passphrase 00173 * will be used to perform encryption; otherwise it will 00174 * be used to perform decryption. 00175 */ 00176 rflag = flag ? Qtrue : Qfalse; 00177 pass = rb_protect(ossl_pem_passwd_cb0, rflag, &status); 00178 if (status) return -1; /* exception was raised. */ 00179 len = RSTRING_LENINT(pass); 00180 if (len < 4) { /* 4 is OpenSSL hardcoded limit */ 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 * Verify callback 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 * main module 00249 */ 00250 VALUE mOSSL; 00251 00252 /* 00253 * OpenSSLError < StandardError 00254 */ 00255 VALUE eOSSLError; 00256 00257 /* 00258 * Convert to DER string 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 * Errors 00283 */ 00284 static VALUE 00285 ossl_make_error(VALUE exc, const char *fmt, va_list args) 00286 { 00287 VALUE str = Qnil; 00288 const char *msg; 00289 long e; 00290 00291 #ifdef HAVE_ERR_PEEK_LAST_ERROR 00292 e = ERR_peek_last_error(); 00293 #else 00294 e = ERR_peek_error(); 00295 #endif 00296 if (fmt) { 00297 str = rb_vsprintf(fmt, args); 00298 } 00299 if (e) { 00300 if (dOSSL == Qtrue) /* FULL INFO */ 00301 msg = ERR_error_string(e, NULL); 00302 else 00303 msg = ERR_reason_error_string(e); 00304 if (NIL_P(str)) { 00305 str = rb_str_new_cstr(msg); 00306 } 00307 else { 00308 rb_str_cat2(rb_str_cat2(str, ": "), msg); 00309 } 00310 } 00311 if (dOSSL == Qtrue){ /* show all errors on the stack */ 00312 while ((e = ERR_get_error()) != 0){ 00313 rb_warn("error on stack: %s", ERR_error_string(e, NULL)); 00314 } 00315 } 00316 ERR_clear_error(); 00317 00318 if (NIL_P(str)) str = rb_str_new(0, 0); 00319 return rb_exc_new3(exc, str); 00320 } 00321 00322 void 00323 ossl_raise(VALUE exc, const char *fmt, ...) 00324 { 00325 va_list args; 00326 VALUE err; 00327 va_start(args, fmt); 00328 err = ossl_make_error(exc, fmt, args); 00329 va_end(args); 00330 rb_exc_raise(err); 00331 } 00332 00333 VALUE 00334 ossl_exc_new(VALUE exc, const char *fmt, ...) 00335 { 00336 va_list args; 00337 VALUE err; 00338 va_start(args, fmt); 00339 err = ossl_make_error(exc, fmt, args); 00340 va_end(args); 00341 return err; 00342 } 00343 00344 /* 00345 * call-seq: 00346 * OpenSSL.errors -> [String...] 00347 * 00348 * See any remaining errors held in queue. 00349 * 00350 * Any errors you see here are probably due to a bug in ruby's OpenSSL implementation. 00351 */ 00352 VALUE 00353 ossl_get_errors() 00354 { 00355 VALUE ary; 00356 long e; 00357 00358 ary = rb_ary_new(); 00359 while ((e = ERR_get_error()) != 0){ 00360 rb_ary_push(ary, rb_str_new2(ERR_error_string(e, NULL))); 00361 } 00362 00363 return ary; 00364 } 00365 00366 /* 00367 * Debug 00368 */ 00369 VALUE dOSSL; 00370 00371 #if !defined(HAVE_VA_ARGS_MACRO) 00372 void 00373 ossl_debug(const char *fmt, ...) 00374 { 00375 va_list args; 00376 00377 if (dOSSL == Qtrue) { 00378 fprintf(stderr, "OSSL_DEBUG: "); 00379 va_start(args, fmt); 00380 vfprintf(stderr, fmt, args); 00381 va_end(args); 00382 fprintf(stderr, " [CONTEXT N/A]\n"); 00383 } 00384 } 00385 #endif 00386 00387 /* 00388 * call-seq: 00389 * OpenSSL.debug -> true | false 00390 */ 00391 static VALUE 00392 ossl_debug_get(VALUE self) 00393 { 00394 return dOSSL; 00395 } 00396 00397 /* 00398 * call-seq: 00399 * OpenSSL.debug = boolean -> boolean 00400 * 00401 * Turns on or off CRYPTO_MEM_CHECK. 00402 * Also shows some debugging message on stderr. 00403 */ 00404 static VALUE 00405 ossl_debug_set(VALUE self, VALUE val) 00406 { 00407 VALUE old = dOSSL; 00408 dOSSL = val; 00409 00410 if (old != dOSSL) { 00411 if (dOSSL == Qtrue) { 00412 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); 00413 fprintf(stderr, "OSSL_DEBUG: IS NOW ON!\n"); 00414 } else if (old == Qtrue) { 00415 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_OFF); 00416 fprintf(stderr, "OSSL_DEBUG: IS NOW OFF!\n"); 00417 } 00418 } 00419 return val; 00420 } 00421 00422 /* 00423 * OpenSSL provides SSL, TLS and general purpose cryptography. It wraps the 00424 * OpenSSL[http://www.openssl.org/] library. 00425 * 00426 * = Examples 00427 * 00428 * All examples assume you have loaded OpenSSL with: 00429 * 00430 * require 'openssl' 00431 * 00432 * These examples build atop each other. For example the key created in the 00433 * next is used in throughout these examples. 00434 * 00435 * == Keys 00436 * 00437 * === Creating a Key 00438 * 00439 * This example creates a 2048 bit RSA keypair and writes it to the current 00440 * directory. 00441 * 00442 * key = OpenSSL::PKey::RSA.new 2048 00443 * 00444 * open 'private_key.pem', 'w' do |io| io.write key.to_pem end 00445 * open 'public_key.pem', 'w' do |io| io.write key.public_key.to_pem end 00446 * 00447 * === Exporting a Key 00448 * 00449 * Keys saved to disk without encryption are not secure as anyone who gets 00450 * ahold of the key may use it unless it is encrypted. In order to securely 00451 * export a key you may export it with a pass phrase. 00452 * 00453 * cipher = OpenSSL::Cipher::Cipher.new 'AES-128-CBC' 00454 * pass_phrase = 'my secure pass phrase goes here' 00455 * 00456 * key_secure = key.export cipher, pass_phrase 00457 * 00458 * open 'private.secure.pem', 'w' do |io| 00459 * io.write key_secure 00460 * end 00461 * 00462 * OpenSSL::Cipher.ciphers returns a list of available ciphers. 00463 * 00464 * === Loading a Key 00465 * 00466 * A key can also be loaded from a file. 00467 * 00468 * key2 = OpenSSL::PKey::RSA.new File.read 'private_key.pem' 00469 * key2.public? # => true 00470 * 00471 * or 00472 * 00473 * key3 = OpenSSL::PKey::RSA.new File.read 'public_key.pem' 00474 * key3.private? # => false 00475 * 00476 * === Loading an Encrypted Key 00477 * 00478 * OpenSSL will prompt you for your pass phrase when loading an encrypted key. 00479 * If you will not be able to type in the pass phrase you may provide it when 00480 * loading the key: 00481 * 00482 * key4_pem = File.read 'private.secure.pem' 00483 * key4 = OpenSSL::PKey::RSA.new key4_pem, pass_phrase 00484 * 00485 * == RSA Encryption 00486 * 00487 * RSA provides ecryption and decryption using the public and private keys. 00488 * You can use a variety of padding methods depending upon the intended use of 00489 * encrypted data. 00490 * 00491 * === Encryption 00492 * 00493 * Documents encrypted with the public key can only be decrypted with the 00494 * private key. 00495 * 00496 * public_encrypted = key.public_encrypt 'top secret document' 00497 * 00498 * Documents encrypted with the private key can only be decrypted with the 00499 * public key. 00500 * 00501 * private_encrypted = key.private_encrypt 'public release document' 00502 * 00503 * === Decryption 00504 * 00505 * Use the opposite key type do decrypt the document 00506 * 00507 * top_secret = key.public_decrypt public_encrypted 00508 * 00509 * public_release = key.private_decrypt private_encrypted 00510 * 00511 * == PKCS #5 Password-based Encryption 00512 * 00513 * PKCS #5 is a password-based encryption standard documented at 00514 * RFC2898[http://www.ietf.org/rfc/rfc2898.txt]. It allows a short password or 00515 * passphrase to be used to create a secure encryption key. 00516 * 00517 * PKCS #5 uses a Cipher, a pass phrase and a salt to generate an encryption 00518 * key. 00519 * 00520 * pass_phrase = 'my secure pass phrase goes here' 00521 * salt = '8 octets' 00522 * 00523 * === Encryption 00524 * 00525 * First set up the cipher for encryption 00526 * 00527 * encrypter = OpenSSL::Cipher::Cipher.new 'AES-128-CBC' 00528 * encrypter.encrypt 00529 * encrypter.pkcs5_keyivgen pass_phrase, salt 00530 * 00531 * Then pass the data you want to encrypt through 00532 * 00533 * encrypted = encrypter.update 'top secret document' 00534 * encrypted << encrypter.final 00535 * 00536 * === Decryption 00537 * 00538 * Use a new Cipher instance set up for decryption 00539 * 00540 * decrypter = OpenSSL::Cipher::Cipher.new 'AES-128-CBC' 00541 * decrypter.decrypt 00542 * decrypter.pkcs5_keyivgen pass_phrase, salt 00543 * 00544 * Then pass the data you want to decrypt through 00545 * 00546 * plain = decrypter.update encrypted 00547 * plain << decrypter.final 00548 * 00549 * == X509 Certificates 00550 * 00551 * === Creating a Certificate 00552 * 00553 * This example creates a self-signed certificate using an RSA key and a SHA1 00554 * signature. 00555 * 00556 * name = OpenSSL::X509::Name.parse 'CN=nobody/DC=example' 00557 * 00558 * cert = OpenSSL::X509::Certificate.new 00559 * cert.version = 2 00560 * cert.serial = 0 00561 * cert.not_before = Time.now 00562 * cert.not_after = Time.now + 3600 00563 * 00564 * cert.public_key = key.public_key 00565 * cert.subject = name 00566 * 00567 * === Certificate Extensions 00568 * 00569 * You can add extensions to the certificate with 00570 * OpenSSL::SSL::ExtensionFactory to indicate the purpose of the certificate. 00571 * 00572 * extension_factory = OpenSSL::X509::ExtensionFactory.new nil, cert 00573 * 00574 * extension_factory.create_extension 'basicConstraints', 'CA:FALSE' 00575 * extension_factory.create_extension 'keyUsage', 00576 * 'keyEncipherment,dataEncipherment,digitalSignature' 00577 * extension_factory.create_extension 'subjectKeyIdentifier', 'hash' 00578 * 00579 * === Signing a Certificate 00580 * 00581 * To sign a certificate set the issuer and use OpenSSL::X509::Certificate#sign 00582 * with a digest algorithm. This creates a self-signed cert because we're using 00583 * the same name and key to sign the certificate as was used to create the 00584 * certificate. 00585 * 00586 * cert.issuer = name 00587 * cert.sign key, OpenSSL::Digest::SHA1.new 00588 * 00589 * open 'certificate.pem', 'w' do |io| io.write cert.to_pem end 00590 * 00591 * === Loading a Certificate 00592 * 00593 * Like a key, a cert can also be loaded from a file. 00594 * 00595 * cert2 = OpenSSL::X509::Certificate.new File.read 'certificate.pem' 00596 * 00597 * === Verifying a Certificate 00598 * 00599 * Certificate#verify will return true when a certificate was signed with the 00600 * given public key. 00601 * 00602 * raise 'certificate can not be verified' unless cert2.verify key 00603 * 00604 * == Certificate Authority 00605 * 00606 * A certificate authority (CA) is a trusted third party that allows you to 00607 * verify the ownership of unknown certificates. The CA issues key signatures 00608 * that indicate it trusts the user of that key. A user encountering the key 00609 * can verify the signature by using the CA's public key. 00610 * 00611 * === CA Key 00612 * 00613 * CA keys are valuable, so we encrypt and save it to disk and make sure it is 00614 * not readable by other users. 00615 * 00616 * ca_key = OpenSSL::PKey::RSA.new 2048 00617 * 00618 * cipher = OpenSSL::Cipher::Cipher.new 'AES-128-CBC' 00619 * 00620 * open 'ca_key.pem', 'w', 0400 do |io| 00621 * io.write key.export(cipher, pass_phrase) 00622 * end 00623 * 00624 * === CA Certificate 00625 * 00626 * A CA certificate is created the same way we created a certificate above, but 00627 * with different extensions. 00628 * 00629 * ca_name = OpenSSL::X509::Name.parse 'CN=ca/DC=example' 00630 * 00631 * ca_cert = OpenSSL::X509::Certificate.new 00632 * ca_cert.serial = 0 00633 * ca_cert.version = 2 00634 * ca_cert.not_before = Time.now 00635 * ca_cert.not_after = Time.now + 86400 00636 * 00637 * ca_cert.public_key = ca_key.public_key 00638 * ca_cert.subject = ca_name 00639 * ca_cert.issuer = ca_name 00640 * 00641 * extension_factory = OpenSSL::X509::ExtensionFactory.new 00642 * extension_factory.subject_certificate = ca_cert 00643 * extension_factory.issuer_certificate = ca_cert 00644 * 00645 * extension_factory.create_extension 'subjectKeyIdentifier', 'hash' 00646 * 00647 * This extension indicates the CA's key may be used as a CA. 00648 * 00649 * extension_factory.create_extension 'basicConstraints', 'CA:TRUE', true 00650 * 00651 * This extension indicates the CA's key may be used to verify signatures on 00652 * both certificates and certificate revocations. 00653 * 00654 * extension_factory.create_extension 'keyUsage', 'cRLSign,keyCertSign', true 00655 * 00656 * Root CA certificates are self-signed. 00657 * 00658 * ca_cert.sign ca_key, OpenSSL::Digest::SHA1.new 00659 * 00660 * The CA certificate is saved to disk so it may be distributed to all the 00661 * users of the keys this CA will sign. 00662 * 00663 * open 'ca_cert.pem', 'w' do |io| 00664 * io.write ca_cert.to_pem 00665 * end 00666 * 00667 * === Certificate Signing Request 00668 * 00669 * The CA signs keys through a Certificate Signing Request (CSR). The CSR 00670 * contains the information necessary to identify the key. 00671 * 00672 * csr = OpenSSL::X509::Request.new 00673 * csr.version = 0 00674 * csr.subject = name 00675 * csr.public_key = key.public_key 00676 * csr.sign key, OpenSSL::Digest::SHA1.new 00677 * 00678 * A CSR is saved to disk and sent to the CA for signing. 00679 * 00680 * open 'csr.pem', 'w' do |io| 00681 * io.write csr.to_pem 00682 * end 00683 * 00684 * === Creating a Certificate from a CSR 00685 * 00686 * Upon receiving a CSR the CA will verify it before signing it. A minimal 00687 * verification would be to check the CSR's signature. 00688 * 00689 * csr = OpenSSL::X509::Request.new File.read 'csr.pem' 00690 * 00691 * raise 'CSR can not be verified' unless csr.verify csr.public_key 00692 * 00693 * After verification a certificate is created, marked for various usages, 00694 * signed with the CA key and returned to the requester. 00695 * 00696 * csr_cert = OpenSSL::X509::Certificate.new 00697 * csr_cert.serial = 0 00698 * csr_cert.version = 2 00699 * csr_cert.not_before = Time.now 00700 * csr_cert.not_after = Time.now + 600 00701 * 00702 * csr_cert.subject = csr.subject 00703 * csr_cert.public_key = csr.public_key 00704 * csr_cert.issuer = ca_cert.subject 00705 * 00706 * extension_factory = OpenSSL::X509::ExtensionFactory.new 00707 * extension_factory.subject_certificate = csr_cert 00708 * extension_factory.issuer_certificate = ca_cert 00709 * 00710 * extension_factory.create_extension 'basicConstraints', 'CA:FALSE' 00711 * extension_factory.create_extension 'keyUsage', 00712 * 'keyEncipherment,dataEncipherment,digitalSignature' 00713 * extension_factory.create_extension 'subjectKeyIdentifier', 'hash' 00714 * 00715 * csr_cert.sign ca_key, OpenSSL::Digest::SHA1.new 00716 * 00717 * open 'csr_cert.pem', 'w' do |io| 00718 * io.write csr_cert.to_pem 00719 * end 00720 * 00721 * == SSL and TLS Connections 00722 * 00723 * Using our created key and certificate we can create an SSL or TLS connection. 00724 * An SSLContext is used to set up an SSL session. 00725 * 00726 * context = OpenSSL::SSL::SSLContext.new 00727 * 00728 * === SSL Server 00729 * 00730 * An SSL server requires the certificate and private key to communicate 00731 * securely with its clients: 00732 * 00733 * context.cert = cert 00734 * context.key = key 00735 * 00736 * Then create an SSLServer with a TCP server socket and the context. Use the 00737 * SSLServer like an ordinary TCP server. 00738 * 00739 * require 'socket' 00740 * 00741 * tcp_server = TCPServer.new 5000 00742 * ssl_server = OpenSSL::SSL::SSLServer.new tcp_server, context 00743 * 00744 * loop do 00745 * ssl_connection = ssl_server.accept 00746 * 00747 * data = connection.gets 00748 * 00749 * response = "I got #{data.dump}" 00750 * puts response 00751 * 00752 * connection.puts "I got #{data.dump}" 00753 * connection.close 00754 * end 00755 * 00756 * === SSL client 00757 * 00758 * An SSL client is created with a TCP socket and the context. 00759 * SSLSocket#connect must be called to initiate the SSL handshake and start 00760 * encryption. A key and certificate are not required for the client socket. 00761 * 00762 * require 'socket' 00763 * 00764 * tcp_client = TCPSocket.new 'localhost', 5000 00765 * ssl_client = OpenSSL::SSL::SSLSocket.new client_socket, context 00766 * ssl_client.connect 00767 * 00768 * ssl_client.puts "hello server!" 00769 * puts ssl_client.gets 00770 * 00771 * === Peer Verification 00772 * 00773 * An unverified SSL connection does not provide much security. For enhanced 00774 * security the client or server can verify the certificate of its peer. 00775 * 00776 * The client can be modified to verify the server's certificate against the 00777 * certificate authority's certificate: 00778 * 00779 * context.ca_file = 'ca_cert.pem' 00780 * context.verify_mode = OpenSSL::SSL::VERIFY_PEER 00781 * 00782 * require 'socket' 00783 * 00784 * tcp_client = TCPSocket.new 'localhost', 5000 00785 * ssl_client = OpenSSL::SSL::SSLSocket.new client_socket, context 00786 * ssl_client.connect 00787 * 00788 * ssl_client.puts "hello server!" 00789 * puts ssl_client.gets 00790 * 00791 * If the server certificate is invalid or <tt>context.ca_file</tt> is not set 00792 * when verifying peers an OpenSSL::SSL::SSLError will be raised. 00793 * 00794 */ 00795 void 00796 Init_openssl() 00797 { 00798 /* 00799 * Init timezone info 00800 */ 00801 #if 0 00802 tzset(); 00803 #endif 00804 00805 /* 00806 * Init all digests, ciphers 00807 */ 00808 /* CRYPTO_malloc_init(); */ 00809 /* ENGINE_load_builtin_engines(); */ 00810 OpenSSL_add_ssl_algorithms(); 00811 OpenSSL_add_all_algorithms(); 00812 ERR_load_crypto_strings(); 00813 SSL_load_error_strings(); 00814 00815 /* 00816 * FIXME: 00817 * On unload do: 00818 */ 00819 #if 0 00820 CONF_modules_unload(1); 00821 destroy_ui_method(); 00822 EVP_cleanup(); 00823 ENGINE_cleanup(); 00824 CRYPTO_cleanup_all_ex_data(); 00825 ERR_remove_state(0); 00826 ERR_free_strings(); 00827 #endif 00828 00829 /* 00830 * Init main module 00831 */ 00832 mOSSL = rb_define_module("OpenSSL"); 00833 00834 /* 00835 * OpenSSL ruby extension version 00836 */ 00837 rb_define_const(mOSSL, "VERSION", rb_str_new2(OSSL_VERSION)); 00838 00839 /* 00840 * Version of OpenSSL the ruby OpenSSL extension was built with 00841 */ 00842 rb_define_const(mOSSL, "OPENSSL_VERSION", rb_str_new2(OPENSSL_VERSION_TEXT)); 00843 /* 00844 * Version number of OpenSSL the ruby OpenSSL extension was built with 00845 * (base 16) 00846 */ 00847 rb_define_const(mOSSL, "OPENSSL_VERSION_NUMBER", INT2NUM(OPENSSL_VERSION_NUMBER)); 00848 00849 /* 00850 * Generic error, 00851 * common for all classes under OpenSSL module 00852 */ 00853 eOSSLError = rb_define_class_under(mOSSL,"OpenSSLError",rb_eStandardError); 00854 00855 /* 00856 * Verify callback Proc index for ext-data 00857 */ 00858 if ((ossl_verify_cb_idx = X509_STORE_CTX_get_ex_new_index(0, (void *)"ossl_verify_cb_idx", 0, 0, 0)) < 0) 00859 ossl_raise(eOSSLError, "X509_STORE_CTX_get_ex_new_index"); 00860 00861 /* 00862 * Init debug core 00863 */ 00864 dOSSL = Qfalse; 00865 rb_define_module_function(mOSSL, "debug", ossl_debug_get, 0); 00866 rb_define_module_function(mOSSL, "debug=", ossl_debug_set, 1); 00867 rb_define_module_function(mOSSL, "errors", ossl_get_errors, 0); 00868 00869 /* 00870 * Get ID of to_der 00871 */ 00872 ossl_s_to_der = rb_intern("to_der"); 00873 00874 /* 00875 * Init components 00876 */ 00877 Init_ossl_bn(); 00878 Init_ossl_cipher(); 00879 Init_ossl_config(); 00880 Init_ossl_digest(); 00881 Init_ossl_hmac(); 00882 Init_ossl_ns_spki(); 00883 Init_ossl_pkcs12(); 00884 Init_ossl_pkcs7(); 00885 Init_ossl_pkcs5(); 00886 Init_ossl_pkey(); 00887 Init_ossl_rand(); 00888 Init_ossl_ssl(); 00889 Init_ossl_x509(); 00890 Init_ossl_ocsp(); 00891 Init_ossl_engine(); 00892 Init_ossl_asn1(); 00893 } 00894 00895 #if defined(OSSL_DEBUG) 00896 /* 00897 * Check if all symbols are OK with 'make LDSHARED=gcc all' 00898 */ 00899 int 00900 main(int argc, char *argv[]) 00901 { 00902 return 0; 00903 } 00904 #endif /* OSSL_DEBUG */ 00905 00906
1.7.6.1