Class: HTTPI::Adapter::OpensslGost
- Inherits:
-
Base
- Object
- Base
- HTTPI::Adapter::OpensslGost
- Defined in:
- lib/httpi/adapter/openssl_gost.rb,
lib/httpi/adapter/openssl_gost/version.rb
Constant Summary collapse
- VERSION =
'0.0.1'
Instance Attribute Summary collapse
-
#client ⇒ Object
readonly
Returns the value of attribute client.
-
#privkey_path ⇒ Object
Returns the value of attribute privkey_path.
-
#pubkey_path ⇒ Object
Returns the value of attribute pubkey_path.
Instance Method Summary collapse
-
#initialize(request) ⇒ OpensslGost
constructor
A new instance of OpensslGost.
- #request(method) ⇒ Object
Constructor Details
#initialize(request) ⇒ OpensslGost
Returns a new instance of OpensslGost.
11 12 13 14 15 |
# File 'lib/httpi/adapter/openssl_gost.rb', line 11 def initialize(request) @request = request @pubkey_path = request.auth.ssl.cert_file @privkey_path = request.auth.ssl.cert_key_file end |
Instance Attribute Details
#client ⇒ Object (readonly)
Returns the value of attribute client.
17 18 19 |
# File 'lib/httpi/adapter/openssl_gost.rb', line 17 def client @client end |
#privkey_path ⇒ Object
Returns the value of attribute privkey_path.
19 20 21 |
# File 'lib/httpi/adapter/openssl_gost.rb', line 19 def privkey_path @privkey_path end |
#pubkey_path ⇒ Object
Returns the value of attribute pubkey_path.
18 19 20 |
# File 'lib/httpi/adapter/openssl_gost.rb', line 18 def pubkey_path @pubkey_path end |
Instance Method Details
#request(method) ⇒ Object
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
# File 'lib/httpi/adapter/openssl_gost.rb', line 21 def request(method) uri = @request.url cmd = "openssl s_client -engine gost -connect '#{uri.host}:#{uri.port}' -quiet" cmd += " -cert '#{pubkey_path}'" if pubkey_path cmd += " -key '#{privkey_path}'" if privkey_path # Prepare request req = "#{method.upcase} #{uri.request_uri} HTTP/1.1\r\n" headers = @request.headers.map{|k,v| "#{k}: #{v}\r\n" }.join # Set up Content-Length header if body present (HTTPI doesn't it for us) if @request.body and !@request.headers['Content-Length'] headers += "Content-Length: #{@request.body.bytesize}\r\n" end # Add hostname header and explicitly close connection (we need command to exit immediately) headers += "Host: #{uri.host}\r\nConnection: close\r\n\r\n" req += headers req += "#{@request.body}\r\n\r\n" if @request.body # Send request, get answer HTTPI.logger.debug "Connecting to server with command: #{cmd}" HTTPI.logger.debug "Sending request:\r\n#{req}" retries = 0 begin raw_response, openssl_stderr, status = Open3.capture3(cmd, stdin_data: req, binmode: true) rescue Errno::EPIPE # Sometimes fails with no reason retry if retries+=1 < 3 end # Check whether command finished correctly and prepare response if status.success? HTTPI.logger.debug "Received response:\r\n#{raw_response}" status_string, headers_and_body = raw_response.split("\r\n", 2) response_headers, response_body = headers_and_body.split("\r\n\r\n", 2) response_code = status_string.scan(/\d{3}/).first response_headers = Hash[response_headers.split("\r\n").map{|h| h.split(':', 2).map(&:strip) }] HTTPI::Response.new(response_code, response_headers, response_body) else HTTPI.logger.fatal "While connecting to server #{uri.host} with command: #{cmd}" HTTPI.logger.fatal "Command returned:\r\n#{status.inspect}" HTTPI.logger.fatal "STDERR is:\n#{openssl_stderr}" # OpenSSL's s_client always return 1 on fail, try to catch most common errors case openssl_stderr when /connect:errno=60/ then raise HTTPI::TimeoutError when /connect:errno=61/ then raise (HTTPI::Error.new).extend(HTTPI::ConnectionError) # Connection refused when /connect:errno=2/ then raise (HTTPI::Error.new).extend(HTTPI::ConnectionError) # No DNS name found when /ssl handshake failure/ then raise HTTPI::SSLError, 'Seems like you trying to connect to HTTP, not HTTPS' when /missing dsa signing cert/ then raise HTTPI::SSLError, 'Probably your OpenSSL lacks GOST configuration' when /unable to load certificate/ then raise HTTPI::SSLError, 'Can not load client certificate, check file path and access rights' when /unable to load .*? private key/ then raise HTTPI::SSLError, 'Can not load client certificate private key, check file path and access rights' else raise HTTPI::Error end end end |