mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Add toplevel documentation for OpenSSL
Add additional documentation for OpenSSL::SSL::SSLContext and OpenSSL::SSL::SSLSocket. Move "let rdoc know about mOSSL" comments so they don't show up in output. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@30090 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
2a35a782ab
commit
41bfc7a721
14 changed files with 623 additions and 56 deletions
|
@ -1,3 +1,11 @@
|
|||
Mon Dec 6 09:45:11 2010 Eric Hodel <drbrain@segment7.net>
|
||||
|
||||
* ext/openssl (OpenSSL): add toplevel documentation
|
||||
* ext/openssl/ossl_ssl.c (SSLContext, SSLSocket: add additional
|
||||
documentation
|
||||
* ext/openssl: move "let rdoc know about mOSSL" comments so they don't
|
||||
show up in output
|
||||
|
||||
Mon Dec 6 09:16:46 2010 NARUSE, Yui <naruse@ruby-lang.org>
|
||||
|
||||
* lib/uri/common.rb (URI::Parser#initialize_pattern):
|
||||
|
|
|
@ -407,7 +407,313 @@ ossl_debug_set(VALUE self, VALUE val)
|
|||
}
|
||||
|
||||
/*
|
||||
* OSSL library init
|
||||
* OpenSSL provides SSL, TLS and general purpose cryptography. It wraps the
|
||||
* OpenSSL[http://www.openssl.org/] library.
|
||||
*
|
||||
* = Examples
|
||||
*
|
||||
* All examples assume you have loaded OpenSSL with:
|
||||
*
|
||||
* require 'openssl'
|
||||
*
|
||||
* These examples build atop each other. For example the key created in the
|
||||
* next is used in throughout these examples.
|
||||
*
|
||||
* == Keys
|
||||
*
|
||||
* === Creating a Key
|
||||
*
|
||||
* This example creates a 2048 bit RSA keypair and writes it to the current
|
||||
* directory.
|
||||
*
|
||||
* key = OpenSSL::PKey::RSA.new 2048
|
||||
*
|
||||
* open 'private_key.pem', 'w' do |io| io.write key.to_pem end
|
||||
* open 'public_key.pem', 'w' do |io| io.write key.public_key.to_pem end
|
||||
*
|
||||
* === Exporting a Key
|
||||
*
|
||||
* Keys saved to disk without encryption are not secure as anyone who gets
|
||||
* ahold of the key may use it unless it is encrypted. In order to securely
|
||||
* export a key you may export it with a pass phrase.
|
||||
*
|
||||
* cipher = OpenSSL::Cipher::Cipher.new 'AES-128-CBC'
|
||||
* pass_phrase = 'my secure pass phrase goes here'
|
||||
*
|
||||
* key_secure = key.export cipher, pass_phrase
|
||||
*
|
||||
* open 'private.secure.pem', 'w' do |io|
|
||||
* io.write key_secure
|
||||
* end
|
||||
*
|
||||
* OpenSSL::Cipher.ciphers returns a list of available ciphers.
|
||||
*
|
||||
* === Loading a Key
|
||||
*
|
||||
* A key can also be loaded from a file.
|
||||
*
|
||||
* key2 = OpenSSL::PKey::RSA.new File.read 'private_key.pem'
|
||||
* key2.public? # => true
|
||||
*
|
||||
* or
|
||||
*
|
||||
* key3 = OpenSSL::PKey::RSA.new File.read 'public_key.pem'
|
||||
* key3.private? # => false
|
||||
*
|
||||
* === Loading an Encrypted Key
|
||||
*
|
||||
* OpenSSL will prompt you for your pass phrase when loading an encrypted key.
|
||||
* If you will not be able to type in the pass phrase you may provide it when
|
||||
* loading the key:
|
||||
*
|
||||
* key4_pem = File.read 'private.secure.pem'
|
||||
* key4 = OpenSSL::PKey::RSA.new key4_pem, pass_phrase
|
||||
*
|
||||
* == X509 Certificates
|
||||
*
|
||||
* === Creating a Certificate
|
||||
*
|
||||
* This example creates a self-signed certificate using an RSA key and a SHA1
|
||||
* signature.
|
||||
*
|
||||
* name = OpenSSL::X509::Name.parse 'CN=nobody/DC=example'
|
||||
*
|
||||
* cert = OpenSSL::X509::Certificate.new
|
||||
* cert.version = 2
|
||||
* cert.serial = 0
|
||||
* cert.not_before = Time.now
|
||||
* cert.not_after = Time.now + 3600
|
||||
*
|
||||
* cert.public_key = key.public_key
|
||||
* cert.subject = name
|
||||
*
|
||||
* === Certificate Extensions
|
||||
*
|
||||
* You can add extensions to the certificate with
|
||||
* OpenSSL::SSL::ExtensionFactory to indicate the purpose of the certificate.
|
||||
*
|
||||
* extension_factory = OpenSSL::X509::ExtensionFactory.new nil, cert
|
||||
*
|
||||
* extension_factory.create_extension 'basicConstraints', 'CA:FALSE'
|
||||
* extension_factory.create_extension 'keyUsage',
|
||||
* 'keyEncipherment,dataEncipherment,digitalSignature'
|
||||
* extension_factory.create_extension 'subjectKeyIdentifier', 'hash'
|
||||
*
|
||||
* === Signing a Certificate
|
||||
*
|
||||
* To sign a certificate set the issuer and use OpenSSL::X509::Certificate#sign
|
||||
* with a digest algorithm. This creates a self-signed cert because we're using
|
||||
* the same name and key to sign the certificate as was used to create the
|
||||
* certificate.
|
||||
*
|
||||
* cert.issuer = name
|
||||
* cert.sign key, OpenSSL::Digest::SHA1.new
|
||||
*
|
||||
* open 'certificate.pem', 'w' do |io| io.write cert.to_pem end
|
||||
*
|
||||
* === Loading a Certificate
|
||||
*
|
||||
* Like a key, a cert can also be loaded from a file.
|
||||
*
|
||||
* cert2 = OpenSSL::X509::Certificate.new File.read 'certificate.pem'
|
||||
*
|
||||
* === Verifying a Certificate
|
||||
*
|
||||
* Certificate#verify will return true when a certificate was signed with the
|
||||
* given public key.
|
||||
*
|
||||
* raise 'certificate can not be verified' unless cert2.verify key
|
||||
*
|
||||
* == Certificate Authority
|
||||
*
|
||||
* A certificate authority (CA) is a trusted third party that allows you to
|
||||
* verify the ownership of unknown certificates. The CA issues key signatures
|
||||
* that indicate it trusts the user of that key. A user encountering the key
|
||||
* can verify the signature by using the CA's public key.
|
||||
*
|
||||
* === CA Key
|
||||
*
|
||||
* CA keys are valuable, so we encrypt and save it to disk and make sure it is
|
||||
* not readable by other users.
|
||||
*
|
||||
* ca_key = OpenSSL::PKey::RSA.new 2048
|
||||
*
|
||||
* cipher = OpenSSL::Cipher::AES.new 128, :CBC
|
||||
*
|
||||
* open 'ca_key.pem', 'w', 0400 do |io|
|
||||
* io.write key.export(cipher, pass_phrase)
|
||||
* end
|
||||
*
|
||||
* === CA Certificate
|
||||
*
|
||||
* A CA certificate is created the same way we created a certificate above, but
|
||||
* with different extensions.
|
||||
*
|
||||
* ca_name = OpenSSL::X509::Name.parse 'CN=ca/DC=example'
|
||||
*
|
||||
* ca_cert = OpenSSL::X509::Certificate.new
|
||||
* ca_cert.serial = 0
|
||||
* ca_cert.version = 2
|
||||
* ca_cert.not_before = Time.now
|
||||
* ca_cert.not_after = Time.now + 86400
|
||||
*
|
||||
* ca_cert.public_key = ca_key.public_key
|
||||
* ca_cert.subject = ca_name
|
||||
* ca_cert.issuer = ca_name
|
||||
*
|
||||
* extension_factory = OpenSSL::X509::ExtensionFactory.new
|
||||
* extension_factory.subject_certificate = ca_cert
|
||||
* extension_factory.issuer_certificate = ca_cert
|
||||
*
|
||||
* extension_factory.create_extension 'subjectKeyIdentifier', 'hash'
|
||||
*
|
||||
* This extension indicates the CA's key may be used as a CA.
|
||||
*
|
||||
* extension_factory.create_extension 'basicConstraints', 'CA:TRUE', true
|
||||
*
|
||||
* This extension indicates the CA's key may be used to verify signatures on
|
||||
* both certificates and certificate revocations.
|
||||
*
|
||||
* extension_factory.create_extension 'keyUsage', 'cRLSign,keyCertSign', true
|
||||
*
|
||||
* Root CA certificates are self-signed.
|
||||
*
|
||||
* ca_cert.sign ca_key, OpenSSL::Digest::SHA1.new
|
||||
*
|
||||
* The CA certificate is saved to disk so it may be distributed to all the
|
||||
* users of the keys this CA will sign.
|
||||
*
|
||||
* open 'ca_cert.pem', 'w' do |io|
|
||||
* io.write ca_cert.to_pem
|
||||
* end
|
||||
*
|
||||
* === Certificate Signing Request
|
||||
*
|
||||
* The CA signs keys through a Certificate Signing Request (CSR). The CSR
|
||||
* contains the information necessary to identify the key.
|
||||
*
|
||||
* csr = OpenSSL::X509::Request.new
|
||||
* csr.version = 0
|
||||
* csr.subject = name
|
||||
* csr.public_key = key.public_key
|
||||
* csr.sign key, OpenSSL::Digest::SHA1.new
|
||||
*
|
||||
* A CSR is saved to disk and sent to the CA for signing.
|
||||
*
|
||||
* open 'csr.pem', 'w' do |io|
|
||||
* io.write csr.to_pem
|
||||
* end
|
||||
*
|
||||
* === Creating a Certificate from a CSR
|
||||
*
|
||||
* Upon receiving a CSR the CA will verify it before signing it. A minimal
|
||||
* verification would be to check the CSR's signature.
|
||||
*
|
||||
* csr = OpenSSL::X509::Request.new File.read 'csr.pem'
|
||||
*
|
||||
* raise 'CSR can not be verified' unless csr.verify csr.public_key
|
||||
*
|
||||
* After verification a certificate is created, marked for various usages,
|
||||
* signed with the CA key and returned to the requester.
|
||||
*
|
||||
* csr_cert = OpenSSL::X509::Certificate.new
|
||||
* csr_cert.serial = 0
|
||||
* csr_cert.version = 2
|
||||
* csr_cert.not_before = Time.now
|
||||
* csr_cert.not_after = Time.now + 600
|
||||
*
|
||||
* csr_cert.subject = csr.subject
|
||||
* csr_cert.public_key = csr.public_key
|
||||
* csr_cert.issuer = ca_cert.subject
|
||||
*
|
||||
* extension_factory = OpenSSL::X509::ExtensionFactory.new
|
||||
* extension_factory.subject_certificate = csr_cert
|
||||
* extension_factory.issuer_certificate = ca_cert
|
||||
*
|
||||
* extension_factory.create_extension 'basicConstraints', 'CA:FALSE'
|
||||
* extension_factory.create_extension 'keyUsage',
|
||||
* 'keyEncipherment,dataEncipherment,digitalSignature'
|
||||
* extension_factory.create_extension 'subjectKeyIdentifier', 'hash'
|
||||
*
|
||||
* csr_cert.sign ca_key, OpenSSL::Digest::SHA1.new
|
||||
*
|
||||
* open 'csr_cert.pem', 'w' do |io|
|
||||
* io.write csr_cert.to_pem
|
||||
* end
|
||||
*
|
||||
* == SSL and TLS Connections
|
||||
*
|
||||
* Using our created key and certificate we can create an SSL or TLS connection.
|
||||
* An SSLContext is used to set up an SSL session.
|
||||
*
|
||||
* context = OpenSSL::SSL::SSLContext.new
|
||||
*
|
||||
* === SSL Server
|
||||
*
|
||||
* An SSL server requires the certificate and private key to communicate
|
||||
* securely with its clients:
|
||||
*
|
||||
* context.cert = cert
|
||||
* context.key = key
|
||||
*
|
||||
* Then create an SSLServer with a TCP server socket and the context. Use the
|
||||
* SSLServer like an ordinary TCP server.
|
||||
*
|
||||
* require 'socket'
|
||||
*
|
||||
* tcp_server = TCPServer.new 5000
|
||||
* ssl_server = OpenSSL::SSL::SSLServer.new tcp_server, context
|
||||
*
|
||||
* loop do
|
||||
* ssl_connection = ssl_server.accept
|
||||
*
|
||||
* data = connection.gets
|
||||
*
|
||||
* response = "I got #{data.dump}"
|
||||
* puts response
|
||||
*
|
||||
* connection.puts "I got #{data.dump}"
|
||||
* connection.close
|
||||
* end
|
||||
*
|
||||
* === SSL client
|
||||
*
|
||||
* An SSL client is created with a TCP socket and the context.
|
||||
* SSLSocket#connect must be called to initiate the SSL handshake and start
|
||||
* encryption. A key and certificate are not required for the client socket.
|
||||
*
|
||||
* require 'socket'
|
||||
*
|
||||
* tcp_client = TCPSocket.new 'localhost', 5000
|
||||
* ssl_client = OpenSSL::SSL::SSLSocket.new client_socket, context
|
||||
* ssl_client.connect
|
||||
*
|
||||
* ssl_client.puts "hello server!"
|
||||
* puts ssl_client.gets
|
||||
*
|
||||
* === Peer Verification
|
||||
*
|
||||
* An unverified SSL connection does not provide much security. For enhanced
|
||||
* security the client or server can verify the certificate the of its peer.
|
||||
*
|
||||
* The client can be modified to verify the server's certificate against the
|
||||
* certificate authority's certificate:
|
||||
*
|
||||
* context.ca_file = 'ca_cert.pem'
|
||||
* context.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
||||
*
|
||||
* require 'socket'
|
||||
*
|
||||
* tcp_client = TCPSocket.new 'localhost', 5000
|
||||
* ssl_client = OpenSSL::SSL::SSLSocket.new client_socket, context
|
||||
* ssl_client.connect
|
||||
*
|
||||
* ssl_client.puts "hello server!"
|
||||
* puts ssl_client.gets
|
||||
*
|
||||
* If the server certificate is invalid or <tt>context.ca_file</tt> is not set
|
||||
* when verifying peers an OpenSSL::SSL::SSLError will be raised.
|
||||
*
|
||||
*/
|
||||
void
|
||||
Init_openssl()
|
||||
|
|
|
@ -1087,8 +1087,8 @@ Init_ossl_asn1()
|
|||
VALUE ary;
|
||||
int i;
|
||||
|
||||
#if 0 /* let rdoc know about mOSSL */
|
||||
mOSSL = rb_define_module("OpenSSL");
|
||||
#if 0
|
||||
mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */
|
||||
#endif
|
||||
|
||||
sUNIVERSAL = rb_intern("UNIVERSAL");
|
||||
|
|
|
@ -731,8 +731,8 @@ ossl_bn_is_prime_fasttest(int argc, VALUE *argv, VALUE self)
|
|||
void
|
||||
Init_ossl_bn()
|
||||
{
|
||||
#if 0 /* let rdoc know about mOSSL */
|
||||
mOSSL = rb_define_module("OpenSSL");
|
||||
#if 0
|
||||
mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */
|
||||
#endif
|
||||
|
||||
if (!(ossl_bn_ctx = BN_CTX_new())) {
|
||||
|
|
|
@ -518,8 +518,8 @@ static VALUE ossl_cipher_block_size() { }
|
|||
void
|
||||
Init_ossl_cipher(void)
|
||||
{
|
||||
#if 0 /* let rdoc know about mOSSL */
|
||||
mOSSL = rb_define_module("OpenSSL");
|
||||
#if 0
|
||||
mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */
|
||||
#endif
|
||||
cCipher = rb_define_class_under(mOSSL, "Cipher", rb_cObject);
|
||||
eCipherError = rb_define_class_under(cCipher, "CipherError", eOSSLError);
|
||||
|
|
|
@ -235,8 +235,8 @@ Init_ossl_digest()
|
|||
{
|
||||
rb_require("digest");
|
||||
|
||||
#if 0 /* let rdoc know about mOSSL */
|
||||
mOSSL = rb_define_module("OpenSSL");
|
||||
#if 0
|
||||
mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */
|
||||
#endif
|
||||
|
||||
cDigest = rb_define_class_under(mOSSL, "Digest", rb_path2class("Digest::Class"));
|
||||
|
|
|
@ -236,8 +236,8 @@ ossl_hmac_s_hexdigest(VALUE klass, VALUE digest, VALUE key, VALUE data)
|
|||
void
|
||||
Init_ossl_hmac()
|
||||
{
|
||||
#if 0 /* let rdoc know about mOSSL */
|
||||
mOSSL = rb_define_module("OpenSSL");
|
||||
#if 0
|
||||
mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */
|
||||
#endif
|
||||
|
||||
eHMACError = rb_define_class_under(mOSSL, "HMACError", eOSSLError);
|
||||
|
|
|
@ -211,8 +211,8 @@ ossl_pkey_verify(VALUE self, VALUE digest, VALUE sig, VALUE data)
|
|||
void
|
||||
Init_ossl_pkey()
|
||||
{
|
||||
#if 0 /* let rdoc know about mOSSL */
|
||||
mOSSL = rb_define_module("OpenSSL");
|
||||
#if 0
|
||||
mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */
|
||||
#endif
|
||||
|
||||
mPKey = rb_define_module_under(mOSSL, "PKey");
|
||||
|
|
|
@ -489,8 +489,8 @@ ossl_create_dh(unsigned char *p, size_t plen, unsigned char *g, size_t glen)
|
|||
void
|
||||
Init_ossl_dh()
|
||||
{
|
||||
#if 0 /* let rdoc know about mOSSL and mPKey */
|
||||
mOSSL = rb_define_module("OpenSSL");
|
||||
#if 0
|
||||
mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL and mPKey */
|
||||
mPKey = rb_define_module_under(mOSSL, "PKey");
|
||||
#endif
|
||||
|
||||
|
|
|
@ -445,8 +445,8 @@ OSSL_PKEY_BN(dsa, priv_key)
|
|||
void
|
||||
Init_ossl_dsa()
|
||||
{
|
||||
#if 0 /* let rdoc know about mOSSL and mPKey */
|
||||
mOSSL = rb_define_module("OpenSSL");
|
||||
#if 0
|
||||
mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL and mPKey */
|
||||
mPKey = rb_define_module_under(mOSSL, "PKey");
|
||||
#endif
|
||||
|
||||
|
|
|
@ -536,8 +536,8 @@ OSSL_PKEY_BN(rsa, iqmp)
|
|||
void
|
||||
Init_ossl_rsa()
|
||||
{
|
||||
#if 0 /* let rdoc know about mOSSL and mPKey */
|
||||
mOSSL = rb_define_module("OpenSSL");
|
||||
#if 0
|
||||
mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL and mPKey */
|
||||
mPKey = rb_define_module_under(mOSSL, "PKey");
|
||||
#endif
|
||||
|
||||
|
|
|
@ -181,8 +181,8 @@ ossl_rand_status(VALUE self)
|
|||
void
|
||||
Init_ossl_rand()
|
||||
{
|
||||
#if 0 /* let rdoc know about mOSSL */
|
||||
mOSSL = rb_define_module("OpenSSL");
|
||||
#if 0
|
||||
mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */
|
||||
#endif
|
||||
|
||||
mRandom = rb_define_module_under(mOSSL, "Random");
|
||||
|
|
|
@ -152,7 +152,7 @@ ossl_sslctx_s_alloc(VALUE klass)
|
|||
* ctx.ssl_version = :TLSv1
|
||||
* ctx.ssl_version = "SSLv23_client"
|
||||
*
|
||||
* You can get a list of valid methods with OpenSSL::SSL::SSLContext::METHODS
|
||||
* You can get a list of valid versions with OpenSSL::SSL::SSLContext::METHODS
|
||||
*/
|
||||
static VALUE
|
||||
ossl_sslctx_set_ssl_version(VALUE self, VALUE ssl_method)
|
||||
|
@ -527,7 +527,8 @@ ssl_servername_cb(SSL *ssl, int *ad, void *arg)
|
|||
* ctx.setup => nil # thereafter
|
||||
*
|
||||
* This method is called automatically when a new SSLSocket is created.
|
||||
* Normally you do not need to call this method (unless you are writing an extension in C).
|
||||
* Normally you do not need to call this method (unless you are writing an
|
||||
* extension in C).
|
||||
*/
|
||||
static VALUE
|
||||
ossl_sslctx_setup(VALUE self)
|
||||
|
@ -687,6 +688,8 @@ ossl_ssl_cipher_to_ary(SSL_CIPHER *cipher)
|
|||
/*
|
||||
* call-seq:
|
||||
* ctx.ciphers => [[name, version, bits, alg_bits], ...]
|
||||
*
|
||||
* The list of ciphers configured for this context.
|
||||
*/
|
||||
static VALUE
|
||||
ossl_sslctx_get_ciphers(VALUE self)
|
||||
|
@ -769,6 +772,7 @@ ossl_sslctx_set_ciphers(VALUE self, VALUE v)
|
|||
* call-seq:
|
||||
* ctx.session_add(session) -> true | false
|
||||
*
|
||||
* Adds +session+ to the session cache
|
||||
*/
|
||||
static VALUE
|
||||
ossl_sslctx_session_add(VALUE self, VALUE arg)
|
||||
|
@ -786,6 +790,7 @@ ossl_sslctx_session_add(VALUE self, VALUE arg)
|
|||
* call-seq:
|
||||
* ctx.session_remove(session) -> true | false
|
||||
*
|
||||
* Removes +session+ from the session cache
|
||||
*/
|
||||
static VALUE
|
||||
ossl_sslctx_session_remove(VALUE self, VALUE arg)
|
||||
|
@ -801,8 +806,9 @@ ossl_sslctx_session_remove(VALUE self, VALUE arg)
|
|||
|
||||
/*
|
||||
* call-seq:
|
||||
* ctx.session_cache_mode -> integer
|
||||
* ctx.session_cache_mode -> Integer
|
||||
*
|
||||
* The current session cache mode.
|
||||
*/
|
||||
static VALUE
|
||||
ossl_sslctx_get_session_cache_mode(VALUE self)
|
||||
|
@ -816,8 +822,11 @@ ossl_sslctx_get_session_cache_mode(VALUE self)
|
|||
|
||||
/*
|
||||
* call-seq:
|
||||
* ctx.session_cache_mode=(integer) -> integer
|
||||
* ctx.session_cache_mode=(integer) -> Integer
|
||||
*
|
||||
* Sets the SSL session cache mode. Bitwise-or together the desired
|
||||
* SESSION_CACHE_* constants to set. See SSL_CTX_set_session_cache_mode(3) for
|
||||
* details.
|
||||
*/
|
||||
static VALUE
|
||||
ossl_sslctx_set_session_cache_mode(VALUE self, VALUE arg)
|
||||
|
@ -833,8 +842,10 @@ ossl_sslctx_set_session_cache_mode(VALUE self, VALUE arg)
|
|||
|
||||
/*
|
||||
* call-seq:
|
||||
* ctx.session_cache_size -> integer
|
||||
* ctx.session_cache_size -> Integer
|
||||
*
|
||||
* Returns the current session cache size. Zero is used to represent an
|
||||
* unlimited cache size.
|
||||
*/
|
||||
static VALUE
|
||||
ossl_sslctx_get_session_cache_size(VALUE self)
|
||||
|
@ -848,8 +859,10 @@ ossl_sslctx_get_session_cache_size(VALUE self)
|
|||
|
||||
/*
|
||||
* call-seq:
|
||||
* ctx.session_cache_size=(integer) -> integer
|
||||
* ctx.session_cache_size=(integer) -> Integer
|
||||
*
|
||||
* Sets the session cache size. Returns the previously valid session cache
|
||||
* size. Zero is used to represent an unlimited session cache size.
|
||||
*/
|
||||
static VALUE
|
||||
ossl_sslctx_set_session_cache_size(VALUE self, VALUE arg)
|
||||
|
@ -867,6 +880,23 @@ ossl_sslctx_set_session_cache_size(VALUE self, VALUE arg)
|
|||
* call-seq:
|
||||
* ctx.session_cache_stats -> Hash
|
||||
*
|
||||
* Returns a Hash containing the following keys:
|
||||
*
|
||||
* :accept:: Number of started SSL/TLS handshakes in server mode
|
||||
* :accept_good:: Number of established SSL/TLS sessions in server mode
|
||||
* :accept_renegotiate:: Number of start renegotiations in server mode
|
||||
* :cache_full:: Number of sessions that were removed due to cache overflow
|
||||
* :cache_hits:: Number of successfully reused connections
|
||||
* :cache_misses:: Number of sessions proposed by clients that were not found
|
||||
* in the cache
|
||||
* :cache_num:: Number of sessions in the internal session cache
|
||||
* :cb_hits:: Number of sessions retrieved from the external cache in server
|
||||
* mode
|
||||
* :connect:: Number of started SSL/TLS handshakes in client mode
|
||||
* :connect_good:: Number of established SSL/TLS sessions in client mode
|
||||
* :connect_renegotiate:: Number of start renegotiations in client mode
|
||||
* :timeouts:: Number of sessions proposed by clients that were found in the
|
||||
* cache but had expired due to timeouts
|
||||
*/
|
||||
static VALUE
|
||||
ossl_sslctx_get_session_cache_stats(VALUE self)
|
||||
|
@ -898,6 +928,7 @@ ossl_sslctx_get_session_cache_stats(VALUE self)
|
|||
* call-seq:
|
||||
* ctx.flush_sessions(time | nil) -> self
|
||||
*
|
||||
* Removes sessions in the internal cache that have expired at +time+.
|
||||
*/
|
||||
static VALUE
|
||||
ossl_sslctx_flush_sessions(int argc, VALUE *argv, VALUE self)
|
||||
|
@ -953,9 +984,11 @@ ossl_ssl_s_alloc(VALUE klass)
|
|||
* SSLSocket.new(io) => aSSLSocket
|
||||
* SSLSocket.new(io, ctx) => aSSLSocket
|
||||
*
|
||||
* === Parameters
|
||||
* * +io+ is a real ruby IO object. Not an IO like object that responds to read/write.
|
||||
* * +ctx+ is an OpenSSLSSL::SSLContext.
|
||||
* Creates a new SSL socket from +io+ which must be a real ruby object (not an
|
||||
* IO-like object that responds to read/write.
|
||||
*
|
||||
* If +ctx+ is provided the SSL Sockets initial params will be taken from
|
||||
* the context.
|
||||
*
|
||||
* The OpenSSL::Buffering module provides additional IO methods.
|
||||
*
|
||||
|
@ -1101,6 +1134,9 @@ ossl_start_ssl(VALUE self, int (*func)(), const char *funcname, int nonblock)
|
|||
/*
|
||||
* call-seq:
|
||||
* ssl.connect => self
|
||||
*
|
||||
* Initiates an SSL/TLS handshake with a server. The handshake may be started
|
||||
* after unencrypted data has been sent over the socket.
|
||||
*/
|
||||
static VALUE
|
||||
ossl_ssl_connect(VALUE self)
|
||||
|
@ -1113,7 +1149,7 @@ ossl_ssl_connect(VALUE self)
|
|||
* call-seq:
|
||||
* ssl.connect_nonblock => self
|
||||
*
|
||||
* initiate the TLS/SSL handshake as a client in non-blocking manner.
|
||||
* Initiates the SSL/TLS handshake as a client in non-blocking manner.
|
||||
*
|
||||
* # emulates blocking connect
|
||||
* begin
|
||||
|
@ -1137,6 +1173,9 @@ ossl_ssl_connect_nonblock(VALUE self)
|
|||
/*
|
||||
* call-seq:
|
||||
* ssl.accept => self
|
||||
*
|
||||
* Waits for a SSL/TLS client to initiate a handshake. The handshake may be
|
||||
* started after unencrypted data has been sent over the socket.
|
||||
*/
|
||||
static VALUE
|
||||
ossl_ssl_accept(VALUE self)
|
||||
|
@ -1149,7 +1188,7 @@ ossl_ssl_accept(VALUE self)
|
|||
* call-seq:
|
||||
* ssl.accept_nonblock => self
|
||||
*
|
||||
* initiate the TLS/SSL handshake as a server in non-blocking manner.
|
||||
* Initiates the SSL/TLS handshake as a server in non-blocking manner.
|
||||
*
|
||||
* # emulates blocking accept
|
||||
* begin
|
||||
|
@ -1235,9 +1274,8 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
|
|||
* ssl.sysread(length) => string
|
||||
* ssl.sysread(length, buffer) => buffer
|
||||
*
|
||||
* === Parameters
|
||||
* * +length+ is a positive integer.
|
||||
* * +buffer+ is a string used to store the result.
|
||||
* Reads +length+ bytes from the SSL connection. If a pre-allocated +buffer+
|
||||
* is provided the data will be written into it.
|
||||
*/
|
||||
static VALUE
|
||||
ossl_ssl_read(int argc, VALUE *argv, VALUE self)
|
||||
|
@ -1250,9 +1288,11 @@ ossl_ssl_read(int argc, VALUE *argv, VALUE self)
|
|||
* ssl.sysread_nonblock(length) => string
|
||||
* ssl.sysread_nonblock(length, buffer) => buffer
|
||||
*
|
||||
* === Parameters
|
||||
* * +length+ is a positive integer.
|
||||
* * +buffer+ is a string used to store the result.
|
||||
* A non-blocking version of #sysread. Raises an SSLError if reading would
|
||||
* block.
|
||||
*
|
||||
* Reads +length+ bytes from the SSL connection. If a pre-allocated +buffer+
|
||||
* is provided the data will be written into it.
|
||||
*/
|
||||
static VALUE
|
||||
ossl_ssl_read_nonblock(int argc, VALUE *argv, VALUE self)
|
||||
|
@ -1304,7 +1344,9 @@ ossl_ssl_write_internal(VALUE self, VALUE str, int nonblock)
|
|||
|
||||
/*
|
||||
* call-seq:
|
||||
* ssl.syswrite(string) => integer
|
||||
* ssl.syswrite(string) => Integer
|
||||
*
|
||||
* Writes +string+ to the SSL connection.
|
||||
*/
|
||||
static VALUE
|
||||
ossl_ssl_write(VALUE self, VALUE str)
|
||||
|
@ -1314,7 +1356,10 @@ ossl_ssl_write(VALUE self, VALUE str)
|
|||
|
||||
/*
|
||||
* call-seq:
|
||||
* ssl.syswrite_nonblock(string) => integer
|
||||
* ssl.syswrite_nonblock(string) => Integer
|
||||
*
|
||||
* Writes +string+ to the SSL connection in a non-blocking manner. Raises an
|
||||
* SSLError if writing would block.
|
||||
*/
|
||||
static VALUE
|
||||
ossl_ssl_write_nonblock(VALUE self, VALUE str)
|
||||
|
@ -1325,6 +1370,8 @@ ossl_ssl_write_nonblock(VALUE self, VALUE str)
|
|||
/*
|
||||
* call-seq:
|
||||
* ssl.sysclose => nil
|
||||
*
|
||||
* Shuts down the SSL connection and prepares it for another connection.
|
||||
*/
|
||||
static VALUE
|
||||
ossl_ssl_close(VALUE self)
|
||||
|
@ -1342,6 +1389,8 @@ ossl_ssl_close(VALUE self)
|
|||
/*
|
||||
* call-seq:
|
||||
* ssl.cert => cert or nil
|
||||
*
|
||||
* The X509 certificate for this socket endpoint.
|
||||
*/
|
||||
static VALUE
|
||||
ossl_ssl_get_cert(VALUE self)
|
||||
|
@ -1370,6 +1419,8 @@ ossl_ssl_get_cert(VALUE self)
|
|||
/*
|
||||
* call-seq:
|
||||
* ssl.peer_cert => cert or nil
|
||||
*
|
||||
* The X509 certificate for this socket's peer.
|
||||
*/
|
||||
static VALUE
|
||||
ossl_ssl_get_peer_cert(VALUE self)
|
||||
|
@ -1399,6 +1450,8 @@ ossl_ssl_get_peer_cert(VALUE self)
|
|||
/*
|
||||
* call-seq:
|
||||
* ssl.peer_cert_chain => [cert, ...] or nil
|
||||
*
|
||||
* The X509 certificate chain for this socket's peer.
|
||||
*/
|
||||
static VALUE
|
||||
ossl_ssl_get_peer_cert_chain(VALUE self)
|
||||
|
@ -1429,6 +1482,8 @@ ossl_ssl_get_peer_cert_chain(VALUE self)
|
|||
/*
|
||||
* call-seq:
|
||||
* ssl.cipher => [name, version, bits, alg_bits]
|
||||
*
|
||||
* The cipher being used for the current connection
|
||||
*/
|
||||
static VALUE
|
||||
ossl_ssl_get_cipher(VALUE self)
|
||||
|
@ -1449,6 +1504,8 @@ ossl_ssl_get_cipher(VALUE self)
|
|||
/*
|
||||
* call-seq:
|
||||
* ssl.state => string
|
||||
*
|
||||
* A description of the current connection state.
|
||||
*/
|
||||
static VALUE
|
||||
ossl_ssl_get_state(VALUE self)
|
||||
|
@ -1471,7 +1528,9 @@ ossl_ssl_get_state(VALUE self)
|
|||
|
||||
/*
|
||||
* call-seq:
|
||||
* ssl.pending => integer
|
||||
* ssl.pending => Integer
|
||||
*
|
||||
* The number of bytes that are immediately available for reading
|
||||
*/
|
||||
static VALUE
|
||||
ossl_ssl_pending(VALUE self)
|
||||
|
@ -1488,9 +1547,10 @@ ossl_ssl_pending(VALUE self)
|
|||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* ssl.session_reused? -> true | false
|
||||
* call-seq:
|
||||
* ssl.session_reused? -> true | false
|
||||
*
|
||||
* Returns true if a reused session was negotiated during the handshake.
|
||||
*/
|
||||
static VALUE
|
||||
ossl_ssl_session_reused(VALUE self)
|
||||
|
@ -1511,9 +1571,10 @@ ossl_ssl_session_reused(VALUE self)
|
|||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* ssl.session = session -> session
|
||||
* call-seq:
|
||||
* ssl.session = session -> session
|
||||
*
|
||||
* Sets the Session to be used when the connection is established.
|
||||
*/
|
||||
static VALUE
|
||||
ossl_ssl_set_session(VALUE self, VALUE arg1)
|
||||
|
@ -1538,6 +1599,15 @@ ossl_ssl_set_session(VALUE self, VALUE arg1)
|
|||
return arg1;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* ssl.verify_result => Integer
|
||||
*
|
||||
* Returns the result of the peer certificates verification. See verify(1)
|
||||
* for error values and descriptions.
|
||||
*
|
||||
* If no peer certificate was presented X509_V_OK is returned.
|
||||
*/
|
||||
static VALUE
|
||||
ossl_ssl_get_verify_result(VALUE self)
|
||||
{
|
||||
|
@ -1558,8 +1628,8 @@ Init_ossl_ssl()
|
|||
int i;
|
||||
VALUE ary;
|
||||
|
||||
#if 0 /* let rdoc know about mOSSL */
|
||||
mOSSL = rb_define_module("OpenSSL");
|
||||
#if 0
|
||||
mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */
|
||||
#endif
|
||||
|
||||
ID_callback_state = rb_intern("@callback_state");
|
||||
|
@ -1577,18 +1647,161 @@ Init_ossl_ssl()
|
|||
|
||||
Init_ossl_ssl_session();
|
||||
|
||||
/* class SSLContext
|
||||
/* Document-class: OpenSSL::SSL::SSLContext
|
||||
*
|
||||
* The following attributes are available but don't show up in rdoc.
|
||||
* All attributes must be set before calling SSLSocket.new(io, ctx).
|
||||
* An SSLContext is used to set various options regarding certificates,
|
||||
* algorithms, verification, session caching, etc. The SSLContext is
|
||||
* used to create an SSLSocket.
|
||||
*
|
||||
* All attributes must be set before creating an SSLSocket as the
|
||||
* SSLContext will be frozen afterward.
|
||||
*
|
||||
* The following attributes are available but don't show up in rdoc:
|
||||
* * ssl_version, cert, key, client_ca, ca_file, ca_path, timeout,
|
||||
* * verify_mode, verify_depth client_cert_cb, tmp_dh_callback,
|
||||
* * session_id_context, session_add_cb, session_new_cb, session_remove_cb
|
||||
*/
|
||||
cSSLContext = rb_define_class_under(mSSL, "SSLContext", rb_cObject);
|
||||
rb_define_alloc_func(cSSLContext, ossl_sslctx_s_alloc);
|
||||
for(i = 0; i < numberof(ossl_sslctx_attrs); i++)
|
||||
rb_attr(cSSLContext, rb_intern(ossl_sslctx_attrs[i]), 1, 1, Qfalse);
|
||||
|
||||
/*
|
||||
* Context certificate
|
||||
*/
|
||||
rb_attr(cSSLContext, rb_intern("cert"), 1, 1, Qfalse);
|
||||
|
||||
/*
|
||||
* Context private key
|
||||
*/
|
||||
rb_attr(cSSLContext, rb_intern("key"), 1, 1, Qfalse);
|
||||
|
||||
/*
|
||||
* A certificate or Array of certificates that will be sent to the client.
|
||||
*/
|
||||
rb_attr(cSSLContext, rb_intern("client_ca"), 1, 1, Qfalse);
|
||||
|
||||
/*
|
||||
* The path to a file containing a PEM-format CA certificate
|
||||
*/
|
||||
rb_attr(cSSLContext, rb_intern("ca_file"), 1, 1, Qfalse);
|
||||
|
||||
/*
|
||||
* The path to a directory containing CA certificates in PEM format.
|
||||
*
|
||||
* Files are looked up by subject's X509 name's hash value.
|
||||
*/
|
||||
rb_attr(cSSLContext, rb_intern("ca_path"), 1, 1, Qfalse);
|
||||
|
||||
/*
|
||||
* Maximum session lifetime.
|
||||
*/
|
||||
rb_attr(cSSLContext, rb_intern("timeout"), 1, 1, Qfalse);
|
||||
|
||||
/*
|
||||
* Session verification mode.
|
||||
*
|
||||
* Valid modes are VERIFY_NONE, VERIFY_PEER, VERIFY_CLIENT_ONCE,
|
||||
* VERIFY_FAIL_IF_NO_PEER_CERT and defined on OpenSSL::SSL
|
||||
*/
|
||||
rb_attr(cSSLContext, rb_intern("verify_mode"), 1, 1, Qfalse);
|
||||
|
||||
/*
|
||||
* Number of CA certificates to walk when verifying a certificate chain.
|
||||
*/
|
||||
rb_attr(cSSLContext, rb_intern("verify_depth"), 1, 1, Qfalse);
|
||||
|
||||
/*
|
||||
* A callback for additional certificate verification. The callback is
|
||||
* invoked for each certificate in the chain.
|
||||
*
|
||||
* The callback is invoked with two values. +preverify_ok+ indicates
|
||||
* indicates if the verification was passed (true) or not (false).
|
||||
* +store_context+ is an OpenSSL::X509::StoreContext containing the
|
||||
* context used for certificate verification.
|
||||
*
|
||||
* If the callback returns false verification is stopped.
|
||||
*/
|
||||
rb_attr(cSSLContext, rb_intern("verify_callback"), 1, 1, Qfalse);
|
||||
|
||||
/*
|
||||
* Sets various OpenSSL options.
|
||||
*/
|
||||
rb_attr(cSSLContext, rb_intern("options"), 1, 1, Qfalse);
|
||||
|
||||
/*
|
||||
* An OpenSSL::X509::Store used for certificate verification
|
||||
*/
|
||||
rb_attr(cSSLContext, rb_intern("cert_store"), 1, 1, Qfalse);
|
||||
|
||||
/*
|
||||
* An Array of extra X509 certificates to be added to the certificate
|
||||
* chain.
|
||||
*/
|
||||
rb_attr(cSSLContext, rb_intern("extra_chain_cert"), 1, 1, Qfalse);
|
||||
|
||||
/*
|
||||
* A callback invoked when a client certificate is requested by a server
|
||||
* and no certificate has been set.
|
||||
*
|
||||
* The callback is invoked with a Session and must return an Array
|
||||
* containing an OpenSSL::X509::Certificate and an OpenSSL::PKey. If any
|
||||
* other value is returned the handshake is suspended.
|
||||
*/
|
||||
rb_attr(cSSLContext, rb_intern("client_cert_cb"), 1, 1, Qfalse);
|
||||
|
||||
/*
|
||||
* A callback invoked when DH parameters are required.
|
||||
*
|
||||
* The callback is invoked with the Session for the key exchange, an
|
||||
* flag indicating the use of an export cipher and the keylength
|
||||
* required.
|
||||
*
|
||||
* The callback must return an OpenSSL::PKey::DH instance of the correct
|
||||
* key length.
|
||||
*/
|
||||
rb_attr(cSSLContext, rb_intern("tmp_dh_callback"), 1, 1, Qfalse);
|
||||
|
||||
/*
|
||||
* Sets the context in which a session can be reused. This allows
|
||||
* sessions for multiple applications to be distinguished, for exapmle, by
|
||||
* name.
|
||||
*/
|
||||
rb_attr(cSSLContext, rb_intern("session_id_context"), 1, 1, Qfalse);
|
||||
|
||||
/*
|
||||
* A callback invoked on a server when a session is proposed by the client
|
||||
* but the session could not be found in the server's internal cache.
|
||||
*
|
||||
* The callback is invoked with the SSLSocket and session id. The
|
||||
* callback may return a Session from an external cache.
|
||||
*/
|
||||
rb_attr(cSSLContext, rb_intern("session_get_cb"), 1, 1, Qfalse);
|
||||
|
||||
/*
|
||||
* A callback invoked when a new session was negotiatied.
|
||||
*
|
||||
* The callback is invoked with an SSLSocket. If false is returned the
|
||||
* session will be removed from the internal cache.
|
||||
*/
|
||||
rb_attr(cSSLContext, rb_intern("session_new_cb"), 1, 1, Qfalse);
|
||||
|
||||
/*
|
||||
* A callback invoked when a session is removed from the internal cache.
|
||||
*
|
||||
* The callback is invoked with an SSLContext and a Session.
|
||||
*/
|
||||
rb_attr(cSSLContext, rb_intern("session_remove_cb"), 1, 1, Qfalse);
|
||||
|
||||
#ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME
|
||||
/*
|
||||
* A callback invoked at connect time to distinguish between multiple
|
||||
* server names.
|
||||
*
|
||||
* The callback is invoked with an SSLSocket and a server name. The
|
||||
* callback must return an SSLContext for the server name or nil.
|
||||
*/
|
||||
rb_attr(cSSLContext, rb_intern("servername_cb"), 1, 1, Qfalse);
|
||||
#endif
|
||||
|
||||
rb_define_alias(cSSLContext, "ssl_timeout", "timeout");
|
||||
rb_define_alias(cSSLContext, "ssl_timeout=", "timeout=");
|
||||
rb_define_method(cSSLContext, "initialize", ossl_sslctx_initialize, -1);
|
||||
|
@ -1599,14 +1812,53 @@ Init_ossl_ssl()
|
|||
rb_define_method(cSSLContext, "setup", ossl_sslctx_setup, 0);
|
||||
|
||||
|
||||
/*
|
||||
* No session caching for client or server
|
||||
*/
|
||||
rb_define_const(cSSLContext, "SESSION_CACHE_OFF", LONG2FIX(SSL_SESS_CACHE_OFF));
|
||||
|
||||
/*
|
||||
* Client sessions are added to the session cache
|
||||
*/
|
||||
rb_define_const(cSSLContext, "SESSION_CACHE_CLIENT", LONG2FIX(SSL_SESS_CACHE_CLIENT)); /* doesn't actually do anything in 0.9.8e */
|
||||
|
||||
/*
|
||||
* Server sessions are added to the session cache
|
||||
*/
|
||||
rb_define_const(cSSLContext, "SESSION_CACHE_SERVER", LONG2FIX(SSL_SESS_CACHE_SERVER));
|
||||
|
||||
/*
|
||||
* Both client and server sessions are added to the session cache
|
||||
*/
|
||||
rb_define_const(cSSLContext, "SESSION_CACHE_BOTH", LONG2FIX(SSL_SESS_CACHE_BOTH)); /* no different than CACHE_SERVER in 0.9.8e */
|
||||
|
||||
/*
|
||||
* Normally the sesison cache is checked for expired sessions every 255
|
||||
* connections. Since this may lead to a delay that cannot be controlled,
|
||||
* the automatic flushing may be disabled and #flush_sessions can be
|
||||
* called explicitly.
|
||||
*/
|
||||
rb_define_const(cSSLContext, "SESSION_CACHE_NO_AUTO_CLEAR", LONG2FIX(SSL_SESS_CACHE_NO_AUTO_CLEAR));
|
||||
|
||||
/*
|
||||
* Always perform external lookups of sessions even if they are in the
|
||||
* internal cache.
|
||||
*
|
||||
* This flag has no effect on clients
|
||||
*/
|
||||
rb_define_const(cSSLContext, "SESSION_CACHE_NO_INTERNAL_LOOKUP", LONG2FIX(SSL_SESS_CACHE_NO_INTERNAL_LOOKUP));
|
||||
|
||||
/*
|
||||
* Never automatically store sessions in the internal store.
|
||||
*/
|
||||
rb_define_const(cSSLContext, "SESSION_CACHE_NO_INTERNAL_STORE", LONG2FIX(SSL_SESS_CACHE_NO_INTERNAL_STORE));
|
||||
|
||||
/*
|
||||
* Enables both SESSION_CACHE_NO_INTERNAL_LOOKUP and
|
||||
* SESSION_CACHE_NO_INTERNAL_STORE.
|
||||
*/
|
||||
rb_define_const(cSSLContext, "SESSION_CACHE_NO_INTERNAL", LONG2FIX(SSL_SESS_CACHE_NO_INTERNAL));
|
||||
|
||||
rb_define_method(cSSLContext, "session_add", ossl_sslctx_session_add, 1);
|
||||
rb_define_method(cSSLContext, "session_remove", ossl_sslctx_session_remove, 1);
|
||||
rb_define_method(cSSLContext, "session_cache_mode", ossl_sslctx_get_session_cache_mode, 0);
|
||||
|
@ -1621,10 +1873,11 @@ Init_ossl_ssl()
|
|||
rb_ary_push(ary, ID2SYM(rb_intern(ossl_ssl_method_tab[i].name)));
|
||||
}
|
||||
rb_obj_freeze(ary);
|
||||
/* holds a list of available SSL/TLS methods */
|
||||
/* The list of available SSL/TLS methods */
|
||||
rb_define_const(cSSLContext, "METHODS", ary);
|
||||
|
||||
/* class SSLSocket
|
||||
/*
|
||||
* Document-class: OpenSSL::SSL::SSLSocket
|
||||
*
|
||||
* The following attributes are available but don't show up in rdoc.
|
||||
* * io, context, sync_close
|
||||
|
|
|
@ -278,8 +278,8 @@ static VALUE ossl_ssl_session_to_text(VALUE self)
|
|||
|
||||
void Init_ossl_ssl_session(void)
|
||||
{
|
||||
#if 0 /* let rdoc know about mOSSL */
|
||||
mOSSL = rb_define_module("OpenSSL");
|
||||
#if 0
|
||||
mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */
|
||||
mSSL = rb_define_module_under(mOSSL, "SSL");
|
||||
#endif
|
||||
cSSLSession = rb_define_class_under(mSSL, "Session", rb_cObject);
|
||||
|
|
Loading…
Reference in a new issue