1 | #
|
---|
2 | # ssl.rb -- SSL/TLS enhancement for GenericServer
|
---|
3 | #
|
---|
4 | # Copyright (c) 2003 GOTOU Yuuzou All rights reserved.
|
---|
5 | #
|
---|
6 | # $Id: ssl.rb 11708 2007-02-12 23:01:19Z shyouhei $
|
---|
7 |
|
---|
8 | require 'webrick'
|
---|
9 | require 'openssl'
|
---|
10 |
|
---|
11 | module WEBrick
|
---|
12 | module Config
|
---|
13 | svrsoft = General[:ServerSoftware]
|
---|
14 | osslv = ::OpenSSL::OPENSSL_VERSION.split[1]
|
---|
15 | SSL = {
|
---|
16 | :ServerSoftware => "#{svrsoft} OpenSSL/#{osslv}",
|
---|
17 | :SSLEnable => false,
|
---|
18 | :SSLCertificate => nil,
|
---|
19 | :SSLPrivateKey => nil,
|
---|
20 | :SSLClientCA => nil,
|
---|
21 | :SSLExtraChainCert => nil,
|
---|
22 | :SSLCACertificateFile => nil,
|
---|
23 | :SSLCACertificatePath => nil,
|
---|
24 | :SSLCertificateStore => nil,
|
---|
25 | :SSLVerifyClient => ::OpenSSL::SSL::VERIFY_NONE,
|
---|
26 | :SSLVerifyDepth => nil,
|
---|
27 | :SSLVerifyCallback => nil, # custom verification
|
---|
28 | :SSLTimeout => nil,
|
---|
29 | :SSLOptions => nil,
|
---|
30 | :SSLStartImmediately => true,
|
---|
31 | # Must specify if you use auto generated certificate.
|
---|
32 | :SSLCertName => nil,
|
---|
33 | :SSLCertComment => "Generated by Ruby/OpenSSL"
|
---|
34 | }
|
---|
35 | General.update(SSL)
|
---|
36 | end
|
---|
37 |
|
---|
38 | module Utils
|
---|
39 | def create_self_signed_cert(bits, cn, comment)
|
---|
40 | rsa = OpenSSL::PKey::RSA.new(bits){|p, n|
|
---|
41 | case p
|
---|
42 | when 0; $stderr.putc "." # BN_generate_prime
|
---|
43 | when 1; $stderr.putc "+" # BN_generate_prime
|
---|
44 | when 2; $stderr.putc "*" # searching good prime,
|
---|
45 | # n = #of try,
|
---|
46 | # but also data from BN_generate_prime
|
---|
47 | when 3; $stderr.putc "\n" # found good prime, n==0 - p, n==1 - q,
|
---|
48 | # but also data from BN_generate_prime
|
---|
49 | else; $stderr.putc "*" # BN_generate_prime
|
---|
50 | end
|
---|
51 | }
|
---|
52 | cert = OpenSSL::X509::Certificate.new
|
---|
53 | cert.version = 3
|
---|
54 | cert.serial = 0
|
---|
55 | name = OpenSSL::X509::Name.new(cn)
|
---|
56 | cert.subject = name
|
---|
57 | cert.issuer = name
|
---|
58 | cert.not_before = Time.now
|
---|
59 | cert.not_after = Time.now + (365*24*60*60)
|
---|
60 | cert.public_key = rsa.public_key
|
---|
61 |
|
---|
62 | ef = OpenSSL::X509::ExtensionFactory.new(nil,cert)
|
---|
63 | ef.issuer_certificate = cert
|
---|
64 | cert.extensions = [
|
---|
65 | ef.create_extension("basicConstraints","CA:FALSE"),
|
---|
66 | ef.create_extension("keyUsage", "keyEncipherment"),
|
---|
67 | ef.create_extension("subjectKeyIdentifier", "hash"),
|
---|
68 | ef.create_extension("extendedKeyUsage", "serverAuth"),
|
---|
69 | ef.create_extension("nsComment", comment),
|
---|
70 | ]
|
---|
71 | aki = ef.create_extension("authorityKeyIdentifier",
|
---|
72 | "keyid:always,issuer:always")
|
---|
73 | cert.add_extension(aki)
|
---|
74 | cert.sign(rsa, OpenSSL::Digest::SHA1.new)
|
---|
75 |
|
---|
76 | return [ cert, rsa ]
|
---|
77 | end
|
---|
78 | module_function :create_self_signed_cert
|
---|
79 | end
|
---|
80 |
|
---|
81 | class GenericServer
|
---|
82 | def ssl_context
|
---|
83 | @ssl_context ||= nil
|
---|
84 | end
|
---|
85 |
|
---|
86 | def listen(address, port)
|
---|
87 | listeners = Utils::create_listeners(address, port, @logger)
|
---|
88 | if @config[:SSLEnable]
|
---|
89 | unless ssl_context
|
---|
90 | @ssl_context = setup_ssl_context(@config)
|
---|
91 | @logger.info("\n" + @config[:SSLCertificate].to_text)
|
---|
92 | end
|
---|
93 | listeners.collect!{|svr|
|
---|
94 | ssvr = ::OpenSSL::SSL::SSLServer.new(svr, ssl_context)
|
---|
95 | ssvr.start_immediately = @config[:SSLStartImmediately]
|
---|
96 | ssvr
|
---|
97 | }
|
---|
98 | end
|
---|
99 | @listeners += listeners
|
---|
100 | end
|
---|
101 |
|
---|
102 | def setup_ssl_context(config)
|
---|
103 | unless config[:SSLCertificate]
|
---|
104 | cn = config[:SSLCertName]
|
---|
105 | comment = config[:SSLCertComment]
|
---|
106 | cert, key = Utils::create_self_signed_cert(1024, cn, comment)
|
---|
107 | config[:SSLCertificate] = cert
|
---|
108 | config[:SSLPrivateKey] = key
|
---|
109 | end
|
---|
110 | ctx = OpenSSL::SSL::SSLContext.new
|
---|
111 | ctx.key = config[:SSLPrivateKey]
|
---|
112 | ctx.cert = config[:SSLCertificate]
|
---|
113 | ctx.client_ca = config[:SSLClientCA]
|
---|
114 | ctx.extra_chain_cert = config[:SSLExtraChainCert]
|
---|
115 | ctx.ca_file = config[:SSLCACertificateFile]
|
---|
116 | ctx.ca_path = config[:SSLCACertificatePath]
|
---|
117 | ctx.cert_store = config[:SSLCertificateStore]
|
---|
118 | ctx.verify_mode = config[:SSLVerifyClient]
|
---|
119 | ctx.verify_depth = config[:SSLVerifyDepth]
|
---|
120 | ctx.verify_callback = config[:SSLVerifyCallback]
|
---|
121 | ctx.timeout = config[:SSLTimeout]
|
---|
122 | ctx.options = config[:SSLOptions]
|
---|
123 | ctx
|
---|
124 | end
|
---|
125 | end
|
---|
126 | end
|
---|