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