OSDN Git Service

ruby-1.9.1-rc1
[splhack/AndroidRuby.git] / lib / ruby-1.9.1-rc1 / ext / openssl / lib / openssl / ssl.rb
1 =begin
2 = $RCSfile$ -- Ruby-space definitions that completes C-space funcs for SSL
3
4 = Info
5   'OpenSSL for Ruby 2' project
6   Copyright (C) 2001 GOTOU YUUZOU <gotoyuzo@notwork.org>
7   All rights reserved.
8
9 = Licence
10   This program is licenced under the same licence as Ruby.
11   (See the file 'LICENCE'.)
12
13 = Version
14   $Id: ssl.rb 14479 2007-12-22 08:31:53Z gotoyuzo $
15 =end
16
17 require "openssl"
18 require "openssl/buffering"
19 require "fcntl"
20
21 module OpenSSL
22   module SSL
23     class SSLContext
24       DEFAULT_PARAMS = {
25         :ssl_version => "SSLv23",
26         :verify_mode => OpenSSL::SSL::VERIFY_PEER,
27         :ciphers => "ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW",
28         :options => OpenSSL::SSL::OP_ALL,
29       }
30
31       DEFAULT_CERT_STORE = OpenSSL::X509::Store.new
32       DEFAULT_CERT_STORE.set_default_paths
33       if defined?(OpenSSL::X509::V_FLAG_CRL_CHECK_ALL)
34         DEFAULT_CERT_STORE.flags = OpenSSL::X509::V_FLAG_CRL_CHECK_ALL
35       end
36
37       def set_params(params={})
38         params = DEFAULT_PARAMS.merge(params)
39         params.each{|name, value| self.__send__("#{name}=", value) }
40         if self.verify_mode != OpenSSL::SSL::VERIFY_NONE
41           unless self.ca_file or self.ca_path or self.cert_store
42             self.cert_store = DEFAULT_CERT_STORE
43           end
44         end
45         return params
46       end
47     end
48
49     module SocketForwarder
50       def addr
51         to_io.addr
52       end
53
54       def peeraddr
55         to_io.peeraddr
56       end
57
58       def setsockopt(level, optname, optval)
59         to_io.setsockopt(level, optname, optval)
60       end
61
62       def getsockopt(level, optname)
63         to_io.getsockopt(level, optname)
64       end
65
66       def fcntl(*args)
67         to_io.fcntl(*args)
68       end
69
70       def closed?
71         to_io.closed?
72       end
73
74       def do_not_reverse_lookup=(flag)
75         to_io.do_not_reverse_lookup = flag
76       end
77     end
78
79     module Nonblock
80       def initialize(*args)
81         flag = File::NONBLOCK
82         flag |= @io.fcntl(Fcntl::F_GETFL) if defined?(Fcntl::F_GETFL)
83         @io.fcntl(Fcntl::F_SETFL, flag)
84         super
85       end
86     end
87
88     def verify_certificate_identity(cert, hostname)
89       should_verify_common_name = true
90       cert.extensions.each{|ext|
91         next if ext.oid != "subjectAltName"
92         ext.value.split(/,\s+/).each{|general_name|
93           if /\ADNS:(.*)/ =~ general_name
94             should_verify_common_name = false
95             reg = Regexp.escape($1).gsub(/\\\*/, "[^.]+")
96             return true if /\A#{reg}\z/i =~ hostname
97           elsif /\AIP Address:(.*)/ =~ general_name
98             should_verify_common_name = false
99             return true if $1 == hostname
100           end
101         }
102       }
103       if should_verify_common_name
104         cert.subject.to_a.each{|oid, value|
105           if oid == "CN"
106             reg = Regexp.escape(value).gsub(/\\\*/, "[^.]+")
107             return true if /\A#{reg}\z/i =~ hostname
108           end
109         }
110       end
111       return false
112     end
113     module_function :verify_certificate_identity
114
115     class SSLSocket
116       include Buffering
117       include SocketForwarder
118       include Nonblock
119
120       def post_connection_check(hostname)
121         unless OpenSSL::SSL.verify_certificate_identity(peer_cert, hostname)
122           raise SSLError, "hostname was not match with the server certificate"
123         end
124         return true
125       end
126
127       def session
128         SSL::Session.new(self)
129       rescue SSL::Session::SessionError
130         nil
131       end
132     end
133
134     class SSLServer
135       include SocketForwarder
136       attr_accessor :start_immediately
137
138       def initialize(svr, ctx)
139         @svr = svr
140         @ctx = ctx
141         unless ctx.session_id_context
142           session_id = OpenSSL::Digest::MD5.hexdigest($0)
143           @ctx.session_id_context = session_id
144         end
145         @start_immediately = true
146       end
147
148       def to_io
149         @svr
150       end
151
152       def listen(backlog=5)
153         @svr.listen(backlog)
154       end
155
156       def shutdown(how=Socket::SHUT_RDWR)
157         @svr.shutdown(how)
158       end
159
160       def accept
161         sock = @svr.accept
162         begin
163           ssl = OpenSSL::SSL::SSLSocket.new(sock, @ctx)
164           ssl.sync_close = true
165           ssl.accept if @start_immediately
166           ssl
167         rescue SSLError => ex
168           sock.close
169           raise ex
170         end
171       end
172
173       def close
174         @svr.close
175       end
176     end
177   end
178 end