'SSL not supported' when calling https web service in Ruby - ruby

I am trying to run the following code to call a webservice from ruby but get an error 'SSL not supported'.
I have httpclient 2.1.5.2 installed.
require 'soap/wsdlDriver'
def validate_certificate(is_ok, ctx)
cert = ctx.current_cert
unless (cert.subject.to_s == cert.issuer.to_s) #check the server certificate only
is_ok &&= File.open(file_name).read == ctx.current_cert.to_pem
end
is_ok
end
def test_webservice
wsdl = "https://.../service.wsdl"
driver = SOAP::WSDLDriverFactory.new(wsdl).create_rpc_driver
driver.options['protocol.http.ssl_config.verify_callback'] = method(:validate_certificate)
driver.method(params)
end

could this be your problem?
http://groups.google.com/group/soap4r/browse_thread/thread/e4d87acac8fe51d5

Related

POST Requests with Ruby Faraday OpenSSL PKCS12

Good day!
I am trying to send POST requests to a server via ssl connection with .p12 certificate from Windows 7 with Ruby's Faraday library.
Ruby's version is ruby 2.3.3p222 (2016-11-21 revision 56859) [x64-mingw32]
Faraday gem's version are: faraday (0.14.0, 0.9.2)
1) I have a folder with the following cert files:
[cert_name].crt,
[cert_name].csr,
[cert_name].key,
[cert_name].p12
2) As to the code, I have the following:
require "faraday"
require "json"
require "openssl"
data = [JSON_object]
host = 'https://[domain_name]'
url = '[string]/[string]'
p12 = OpenSSL::PKCS12.new(File.open('[path_to_folder_with_cert_files]/[cert_name].p12', "rb").read, "[password]")
key = p12.key
cert = p12.certificate
connection = Faraday::Connection.new host, :ssl => {
:client_cert => cert,
:client_key => key,
:ca_file => '[path_to_folder_with_cert_files]/[cert_name].crt',
:verify => false
}
puts response.status = connection.post do |req|
req.url(url)
req.headers['Content-Type'] = #headers["content_type"]
req.body = data
end
Response has 403 Forbidden. I have tested with no ssl connection the data, url, host parameters and the status is 200 OK.
Please help, as I have found no tutorial / question to this particular use of Ruby's Faraday and OpenSSL::PKCS12
The following worked for me:
class Gateway
def call
connection.get do |req|
req.url(url)
req.headers['Content-Type'] = 'text/xml'
req.body = data
end
end
def connection
Faraday.new(ssl: ssl) do |builder|
builder.request :retry
builder.response(:logger) unless Rails.env.test?
builder.adapter :net_http
end
end
def ssl
{
client_key: client_key,
client_cert: client_cert,
ca_file: 'CA.crt' # optional
}
end
def url
'https://...'
end
def client_key
p12.key
end
def client_cert
p12.certificate
end
def p12
OpenSSL::PKCS12.new(p12_file.read, p12_password)
end
def p12_file
File.open('<path-to-p12-file>', 'rb')
end
def p12_password
'password' # if password protected
end
end
And the usage:
puts Gateway.new.call.body

Encrypted Transfer With Ruby FTPS

I am trying to fetch files from a server using FTPS. I'm able to authenticate but when I try to list/fetch the files, I get a "521 Data connections must be encrypted". Is the Net::FTP module capable of this, and how would I accomplish it?
I modified Net::FTPTLS into my own class because I needed to store a self-signed cert.
require 'socket'
require 'openssl'
require 'net/ftp'
module MP
class FTPS < Net::FTP
def connect(host, port=FTP_PORT)
#hostname = host
super
end
def login(user = "anonymous", passwd = nil, cert_file = nil, acct = nil)
store = OpenSSL::X509::Store.new
if cert_file == nil
store.set_default_paths
else
certraw = File.read(cert_file)
cert = OpenSSL::X509::Certificate.new(certraw)
store.add_cert(cert)
end
ctx = OpenSSL::SSL::SSLContext.new('SSLv23')
ctx.cert_store = store
ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER
ctx.key = nil
ctx.cert = cert
voidcmd("AUTH TLS")
#sock = OpenSSL::SSL::SSLSocket.new(#sock, ctx)
#sock.connect
##sock.post_connection_check(#hostname)
super(user, passwd, acct)
voidcmd("PBSZ 0")
end
end
end
And here's the snippet for trying to fetch the files:
def get_ftpclient(host)
FTPS::new(host)
end
def check_for_files
#ftp = get_ftpclient(#host)
#ftp.passive = true
#ftp.login(#user_name, #password, #cert_file)
#ftp.chdir(#remote_dir)
files = #ftp.nlst
files
end
It fails on the nlst.
Edit: I tried adding voidcmd("PROT P") to the end of the login function but it just hangs for a while, then I eventually get:
IOError: Unsupported record version Unknown-48.48
___BEGIN BACKTRACE___
org/jruby/ext/openssl/SSLSocket.java:564:in `sysread'
/opt/jruby/lib/ruby/gems/1.8/gems/jruby-openssl-0.7.6.1/lib/1.8/openssl/buffering.rb:36:in `fill_rbuff'
/opt/jruby/lib/ruby/gems/1.8/gems/jruby-openssl-0.7.6.1/lib/1.8/openssl/buffering.rb:159:in `eof?'
/opt/jruby/lib/ruby/gems/1.8/gems/jruby-openssl-0.7.6.1/lib/1.8/openssl/buffering.rb:134:in `readline'
/opt/jruby/lib/ruby/1.8/net/ftp.rb:211:in `getline'
/opt/jruby/lib/ruby/1.8/net/ftp.rb:221:in `getmultiline'
/opt/jruby/lib/ruby/1.8/net/ftp.rb:235:in `getresp'
/opt/jruby/lib/ruby/1.8/net/ftp.rb:251:in `voidresp'
/opt/jruby/lib/ruby/1.8/net/ftp.rb:436:in `retrlines'
/opt/jruby/lib/ruby/1.8/monitor.rb:191:in `mon_synchronize'
/opt/jruby/lib/ruby/1.8/net/ftp.rb:422:in `retrlines'
/opt/jruby/lib/ruby/1.8/net/ftp.rb:612:in `nlst'
... etc
I realize this is an old question, but I stumbled upon it while researching FTPS ruby gems.
No. net::FTP does not, on its own, support FTPS.
I highly recommend double-bag-ftps.
Provides a child class of Net::FTP to support implicit and explicit FTPS.
Version 0.1.1 has been working beautifully for me running daily for the past year.

ruby 1.9.3 simple GET request to unicorn through socket

Now I try to connect to my socket cretaed by unicorn with this code
require 'socket'
def foo
socket = UNIXSocket.new("path_to_socket/tmp/unicorn.sock")
data = "GET /time HTTP/1.1\n"
data << "Connection: Close\n"
data << "User-Agent: Mozilla/5.0\n"
data << "Accept: */*\n"
data << "Content-Type: application/x-www-form-urlencoded\n"
data << "\n\r\n\r"
socket.puts(data)
while(line = socket.gets) do
puts line
end
end
foo
But always get a "HTTP/1.1 400 Bad Request"
Please, can any body say what I'm do wrong???
Use net/http...
require "net/http"
require "socket"
sock = Net::BufferedIO.new(UNIXSocket.new("path_to_socket/tmp/unicorn.sock"))
request = Net::HTTP::Get.new("/time")
request.exec(sock, "1.1", "/time")
begin
response = Net::HTTPResponse.read_new(sock)
end while response.kind_of?(Net::HTTPContinue)
response.reading_body(sock, request.response_body_permitted?) { }
response.body
response.code
This is very helpful but please note that the Net::HTTP#exec method is marked for internal use only. Likely because it doesn't do resource management, etc.
The following work adapts the suggested strategy to override Net::HTTP#connect (to connect to a socket). I like to use the HTTParty gem for handling my HTTP requests. So the strategy here makes use of a custom ConnectionAdaptor for HTTParty. Now I can just change the ::default_params= call on my including class, to control whether we're using a Unix or a TCP/HTTP socket.
###########################################################
# net/socket_http.rb
###########################################################
module Net
# Overrides the connect method to simply connect to a unix domain socket.
class SocketHttp < HTTP
attr_reader :socket_path
# URI should be a relative URI giving the path on the HTTP server.
# socket_path is the filesystem path to the socket the server is listening to.
def initialize(uri, socket_path)
#socket_path = socket_path
super(uri)
end
# Create the socket object.
def connect
#socket = Net::BufferedIO.new UNIXSocket.new socket_path
on_connect
end
# Override to prevent errors concatenating relative URI objects.
def addr_port
File.basename(socket_path)
end
end
end
###########################################################
# sock_party.rb, a ConnectionAdapter class
###########################################################
require "net/http"
require "socket"
class SockParty < HTTParty::ConnectionAdapter
# Override the base class connection method.
# Only difference is that we'll create a Net::SocketHttp rather than a Net::HTTP.
# Relies on :socket_path in the
def connection
http = Net::SocketHttp.new(uri, options[:socket_path])
if options[:timeout] && (options[:timeout].is_a?(Integer) || options[:timeout].is_a?(Float))
http.open_timeout = options[:timeout]
http.read_timeout = options[:timeout]
end
if options[:debug_output]
http.set_debug_output(options[:debug_output])
end
if options[:ciphers]
http.ciphers = options[:ciphers]
end
return http
end
end
###########################################################
# class MockSockParty, a really *nix-y HTTParty
###########################################################
class MockSockParty
include HTTParty
self.default_options = {connection_adapter: SockParty, socket_path: '/tmp/thin.sock'}
def party_hard
self.class.get('/client').body
end
end
###########################################################
# sock_party_spec.rb
###########################################################
require 'spec_helper'
describe SockParty do
it "should party until its socks fall off." do
puts MockSockParty.new.party_hard
end
end

Ldap gem throws no connection to server exception in Rails

Trying to establish a connection from a module in Rails and get no connection to server. I have tested the same code outside Rails and it works fine.
require 'rubygems'
require 'net-ldap'
module Foo
module Bar
class User
attr_reader :ldap_connection
def initialize
#ldap = Net::LDAP.new(:host => "<ip-number>", :port => 389)
#treebase = "ou=People, dc=foo, dc=bar"
username = "cn=Manager"
password = "password"
#ldap.auth username, password
begin
if #ldap.bind
#ldap_connection = true
else
#ldap_connection = false
end
rescue Net::LDAP::LdapError
#ldap_connection = false
end
end
end
end
end
Getting Net::LDAP::LdapError: no connection to server exception.
I found a solution/workaround for my problem with auto-loading in Rails. Added a new initializer to ensure that all Ruby files under lib/ get required:
Added config/initializers/require_files_in_lib.rb with this code
Dir[Rails.root + 'lib/**/*.rb'].each do |file|
require file
end
Read more about the workaround: Rails 3 library not loading until require

Rails3 omniauth google authentication on Returns User Identity

My Omniauth integration works on local development but fails for google on staging.
require 'omniauth/openid'
require 'openid/store/memcache'
Rails.application.config.middleware.use OmniAuth::Builder do
OmniAuth.config.full_host = "http://xx.xx.xxx/"
# dedicated openid
provider :open_id, OpenID::Store::Memcache.new(Dalli::Client.new), :name => 'google', :identifier => 'https://www.google.com/accounts/o8/id'
end
I get a this error message:
Started GET "/auth/failure?message=invalid_credentials" for 58.71.19.178 at 2011-12-01 02:22:20 +0000
Processing by ErrorsController#routing as HTML
Parameters: {"message"=>"invalid_credentials", "a"=>"auth/failure"}
Rendered public/404.html (0.1ms)
Completed 404 Not Found in 1ms (Views: 0.6ms | ActiveRecord: 0.0ms)
Also the ip in for is not the same in my OmniAuth.config.full_host maybe that could be causing the issue?
The culprit was that apache sending and returning on different ips
This monkey patch fixed the issue.
module OmniAuth
module Strategies
# OmniAuth strategy for connecting via OpenID. This allows for connection
# to a wide variety of sites, some of which are listed [on the OpenID website](http://openid.net/get-an-openid/).
class OpenID
protected
def callback_url
uri = URI.parse(request.url)
uri.path += '/callback'
# by KirylP: to overcome hosting subdomain forwarding to rails port
uri.port = '' if request.env.has_key? 'HTTP_X_FORWARDED_SERVER'
uri.to_s
end
end
end
end
module Rack
class OpenID
SERVER_PORT_TO_AVOID = 12002
private
def realm_url(req)
url = req.scheme + "://"
url << req.host
scheme, port = req.scheme, req.port
if scheme == "https" && port != 443 ||
scheme == "http" && port != 80
url << ":#{port}" if port != SERVER_PORT_TO_AVOID # KirylP
end
url
end
end
end
module OpenID
class Consumer
def complete(query, current_url)
message = Message.from_post_args(query)
current_url.sub!(":#{Rack::OpenID::SERVER_PORT_TO_AVOID}", '') # KirylP
mode = message.get_arg(OPENID_NS, 'mode', 'invalid')
begin
meth = method('complete_' + mode)
rescue NameError
meth = method(:complete_invalid)
end
response = meth.call(message, current_url)
cleanup_last_requested_endpoint
if [SUCCESS, CANCEL].member?(response.status)
cleanup_session
end
return response
end
end
end
I had a similar problem. Seems like your google authentication fails (can be for different reasons - invalid credentials, or user denied access), therefore you receive callback to /auth/failure -- and then you get 404.
Did you implement a route for /auth/failure in your routes.rb? In my current project:
in routes.rb
match '/auth/failure', :to => 'sessions#failure'
in sessions_controller
def failure
redirect_to session[:return_uri] || root_path, alert: "Sorry, we were not able to authenticate you using your chosen sign on method"
end

Resources