Login
[x]
Log in using an account from:
Fedora Account System
Red Hat Associate
Red Hat Customer
Or login using a Red Hat Bugzilla account
Forgot Password
Login:
Hide Forgot
Create an Account
Red Hat Bugzilla – Attachment 866995 Details for
Bug 1058595
CVE-2014-0036 rubygem-rbovirt: unsafe use of rest-client
[?]
New
Simple Search
Advanced Search
My Links
Browse
Requests
Reports
Current State
Search
Tabular reports
Graphical reports
Duplicates
Other Reports
User Changes
Plotly Reports
Bug Status
Bug Severity
Non-Defaults
|
Product Dashboard
Help
Page Help!
Bug Writing Guidelines
What's new
Browser Support Policy
5.0.4.rh83 Release notes
FAQ
Guides index
User guide
Web Services
Contact
Legal
This site requires JavaScript to be enabled to function correctly, please enable it.
[patch]
a patch that fixes the issue.
0001-added-support-for-https-peer-authentication.patch (text/plain), 13.79 KB, created by
Amos Benari
on 2014-02-24 15:22:41 UTC
(
hide
)
Description:
a patch that fixes the issue.
Filename:
MIME Type:
Creator:
Amos Benari
Created:
2014-02-24 15:22:41 UTC
Size:
13.79 KB
patch
obsolete
>From 002e3d6193cde692e9f5e5baf303b7148ccc4a3e Mon Sep 17 00:00:00 2001 >From: Amos Benari <abenari@redhat.com> >Date: Mon, 24 Feb 2014 15:48:53 +0200 >Subject: [PATCH] added support for https peer authentication. > >--- > .gitignore | 1 + > lib/rbovirt.rb | 65 +++++++++++++++++++++++++++++++++------- > lib/restclient_ext/request.rb | 60 +++++++++++++++++++++++++++++++++++++ > spec/endpoint.yml.example | 3 +- > spec/integration/api_spec.rb | 30 ++++++++++++++++--- > spec/integration/vm_crud_spec.rb | 20 ++++++++----- > spec/lib/endpoint.rb | 7 +---- > spec/unit/client_spec.rb | 21 +++++++++++++ > 8 files changed, 176 insertions(+), 31 deletions(-) > create mode 100644 lib/restclient_ext/request.rb > >diff --git a/.gitignore b/.gitignore >index ba655ef..fed5a5d 100644 >--- a/.gitignore >+++ b/.gitignore >@@ -1,5 +1,6 @@ > Gemfile.lock > endpoint.yml >+spec/ca_cert.pem > > # rcov generated > coverage >diff --git a/lib/rbovirt.rb b/lib/rbovirt.rb >index bdcedd3..484a7eb 100644 >--- a/lib/rbovirt.rb >+++ b/lib/rbovirt.rb >@@ -21,6 +21,7 @@ require "client/quota_api" > > require "nokogiri" > require "rest_client" >+require "restclient_ext/request" > > module OVIRT > >@@ -38,14 +39,47 @@ module OVIRT > > class Client > >- attr_reader :credentials, :api_entrypoint, :datacenter_id, :cluster_id, :filtered_api >- >- def initialize(username, password, api_entrypoint, datacenter_id=nil, cluster_id=nil, filtered_api = false) >- @credentials = { :username => username, :password => password } >- @datacenter_id = datacenter_id >- @cluster_id = cluster_id >+ attr_reader :credentials, :api_entrypoint, :datacenter_id, :cluster_id, :filtered_api, :ca_cert_file, :ca_cert_store >+ >+ # Construct a new ovirt client class. >+ # mandatory parameters >+ # username, password, api_entrypoint - for example 'me@internal', 'secret', 'https://example.com/api' >+ # optional parameters >+ # datacenter_id, cluster_id and filtered_api can be sent in this order for backward >+ # compatibility, or as a hash in the 4th parameter. >+ # datacenter_id - setting the datacenter at initialization will add a default scope to any subsequent call >+ # to the client to the specified datacenter. >+ # cluster_id - setting the cluster at initialization will add a default scope to any subsequent call >+ # to the client to the specified cluster. >+ # filtered_api - when set to false (default) will use ovirt administrator api, else it will use the user >+ # api mode. >+ # >+ def initialize(username, password, api_entrypoint, options={}, backward_compatibility_cluster=nil, backward_compatibility_filtered=nil ) >+ if !options.is_a?(Hash) >+ # backward compatibility optional parameters >+ options = {:datacenter_id => options, >+ :cluster_id => backward_compatibility_cluster, >+ :filtered_api => backward_compatibility_filtered} >+ end > @api_entrypoint = api_entrypoint >- @filtered_api = filtered_api >+ @credentials = { :username => username, :password => password } >+ @datacenter_id = options[:datacenter_id] >+ @cluster_id = options[:cluster_id] >+ @filtered_api = options[:filtered_api] >+ @ca_cert_file = options[:ca_cert_file] >+ @ca_cert_store = options[:ca_cert_store] >+ end >+ >+ # get ovirt ca certificate public key >+ # * url - ovirt server url >+ def self.ca_cert(url) >+ ca_url = URI.parse(url) >+ ca_url.path = "/ca.crt" >+ http = Net::HTTP.new(ca_url.host, ca_url.port) >+ http.use_ssl = (ca_url.scheme == 'https') >+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE >+ request = Net::HTTP::Get.new(ca_url.path) >+ http.request(request).body > end > > def api_version >@@ -79,7 +113,7 @@ module OVIRT > > def http_get(suburl, headers={}) > begin >- Nokogiri::XML(RestClient::Resource.new(@api_entrypoint)[suburl].get(http_headers(headers))) >+ Nokogiri::XML(rest_client(suburl).get(http_headers(headers))) > rescue > handle_fault $! > end >@@ -87,7 +121,7 @@ module OVIRT > > def http_post(suburl, body, headers={}) > begin >- Nokogiri::XML(RestClient::Resource.new(@api_entrypoint)[suburl].post(body, http_headers(headers))) >+ Nokogiri::XML(rest_client(suburl).post(body, http_headers(headers))) > rescue > handle_fault $! > end >@@ -95,7 +129,7 @@ module OVIRT > > def http_put(suburl, body, headers={}) > begin >- Nokogiri::XML(RestClient::Resource.new(@api_entrypoint)[suburl].put(body, http_headers(headers))) >+ Nokogiri::XML(rest_client(suburl).put(body, http_headers(headers))) > rescue > handle_fault $! > end >@@ -104,7 +138,7 @@ module OVIRT > def http_delete(suburl) > begin > headers = {:accept => 'application/xml'}.merge(auth_header).merge(filter_header) >- Nokogiri::XML(RestClient::Resource.new(@api_entrypoint)[suburl].delete(headers)) >+ Nokogiri::XML(rest_client(suburl).delete(headers)) > rescue > handle_fault $! > end >@@ -116,6 +150,15 @@ module OVIRT > { :authorization => "Basic " + encoded_credentials } > end > >+ def rest_client(suburl) >+ if (URI.parse(@api_entrypoint)).scheme == 'https' >+ verify_options = {:verify_ssl => OpenSSL::SSL::VERIFY_PEER} >+ verify_options[:ssl_cert_store] = ca_cert_store if ca_cert_store >+ verify_options[:ssl_ca_file] = ca_cert_file if ca_cert_file >+ end >+ RestClient::Resource.new(@api_entrypoint, verify_options)[suburl] >+ end >+ > def filter_header > filtered_api ? { :filter => "true" } : {} > end >diff --git a/lib/restclient_ext/request.rb b/lib/restclient_ext/request.rb >new file mode 100644 >index 0000000..0070b6b >--- /dev/null >+++ b/lib/restclient_ext/request.rb >@@ -0,0 +1,60 @@ >+# rest-client extension >+module RestClient >+ # This class enhance the rest-client request by accepting a parameter for ca certificate store, >+ # this file can be removed once https://github.com/rest-client/rest-client/pull/254 >+ # get merged upstream. >+ # >+ # :ssl_cert_store - an x509 certificate store. >+ class Request >+ >+ def transmit uri, req, payload, & block >+ setup_credentials req >+ >+ net = net_http_class.new(uri.host, uri.port) >+ net.use_ssl = uri.is_a?(URI::HTTPS) >+ if (@verify_ssl == false) || (@verify_ssl == OpenSSL::SSL::VERIFY_NONE) >+ net.verify_mode = OpenSSL::SSL::VERIFY_NONE >+ elsif @verify_ssl.is_a? Integer >+ net.verify_mode = @verify_ssl >+ net.verify_callback = lambda do |preverify_ok, ssl_context| >+ if (!preverify_ok) || ssl_context.error != 0 >+ err_msg = "SSL Verification failed -- Preverify: #{preverify_ok}, Error: #{ssl_context.error_string} (#{ssl_context.error})" >+ raise SSLCertificateNotVerified.new(err_msg) >+ end >+ true >+ end >+ end >+ net.cert = @ssl_client_cert if @ssl_client_cert >+ net.key = @ssl_client_key if @ssl_client_key >+ net.ca_file = @ssl_ca_file if @ssl_ca_file >+ net.cert_store = args[:ssl_cert_store] if args[:ssl_cert_store] >+ net.read_timeout = @timeout if @timeout >+ net.open_timeout = @open_timeout if @open_timeout >+ >+ # disable the timeout if the timeout value is -1 >+ net.read_timeout = nil if @timeout == -1 >+ net.out_timeout = nil if @open_timeout == -1 >+ >+ RestClient.before_execution_procs.each do |before_proc| >+ before_proc.call(req, args) >+ end >+ >+ log_request >+ >+ net.start do |http| >+ if @block_response >+ http.request(req, payload ? payload.to_s : nil, & @block_response) >+ else >+ res = http.request(req, payload ? payload.to_s : nil) { |http_response| fetch_body(http_response) } >+ log_response res >+ process_result res, & block >+ end >+ end >+ rescue EOFError >+ raise RestClient::ServerBrokeConnection >+ rescue Timeout::Error >+ raise RestClient::RequestTimeout >+ end >+ >+ end >+end >diff --git a/spec/endpoint.yml.example b/spec/endpoint.yml.example >index 4730d00..77224aa 100644 >--- a/spec/endpoint.yml.example >+++ b/spec/endpoint.yml.example >@@ -1,5 +1,4 @@ > > user: "admin@internal" > password: "secret" >-hostname: "ovirt.example.com" >-port: "" >+url: "http://ovirt.example.com/api" >diff --git a/spec/integration/api_spec.rb b/spec/integration/api_spec.rb >index 3fcb21a..5e7c22e 100644 >--- a/spec/integration/api_spec.rb >+++ b/spec/integration/api_spec.rb >@@ -38,11 +38,32 @@ shared_examples_for "API" do > end > end > >+describe OVIRT, "Https authentication" do >+ context 'authenticate using the server ca certificate' do >+ >+ it "test_should_get_ca_certificate" do >+ user, password, url, datacenter = endpoint >+ ::OVIRT::Client.ca_cert(url).class.should eql(String) >+ end >+ >+ it "should_authenticate_with_ca_certificate" do >+ user, password, url, datacenter = endpoint >+ cert = ::OVIRT::Client.ca_cert(url) >+ store = OpenSSL::X509::Store.new().add_cert( >+ OpenSSL::X509::Certificate.new(cert)) >+ >+ client = ::OVIRT::Client.new(user, password, url, {:ca_cert_store => store}) >+ client.api_version.class.should eql(String) >+ end >+ end >+end >+ > describe OVIRT, "Admin API" do > > before(:all) do >- user, password, url = endpoint >- @client = ::OVIRT::Client.new(user, password, url, nil, nil, false) >+ user, password, url, datacenter = endpoint >+ opts = {:datacenter_id => datacenter, :ca_cert_file => "#{File.dirname(__FILE__)}/../ca_cert.pem"} >+ @client = ::OVIRT::Client.new(user, password, url, opts ) > end > > after(:all) do >@@ -61,8 +82,9 @@ end > describe OVIRT, "User API" do > > before(:all) do >- user, password, url = endpoint >- @client = ::OVIRT::Client.new(user, password, url, nil, nil, support_user_level_api) >+ user, password, url, datacenter = endpoint >+ opts = {:datacenter_id => datacenter, :ca_cert_file => "#{File.dirname(__FILE__)}/../ca_cert.pem", :filtered_api => support_user_level_api} >+ @client = ::OVIRT::Client.new(user, password, url, opts) > end > > after(:all) do >diff --git a/spec/integration/vm_crud_spec.rb b/spec/integration/vm_crud_spec.rb >index 42e9ca0..61c5293 100644 >--- a/spec/integration/vm_crud_spec.rb >+++ b/spec/integration/vm_crud_spec.rb >@@ -3,12 +3,12 @@ require "#{File.dirname(__FILE__)}/../spec_helper" > shared_examples_for "Basic VM Life cycle" do > > before(:all) do >- @blank_template_id = "00000000-0000-0000-0000-000000000000" >- @cluster = @client.clusters.first.id >+ @cluster = @client.clusters.last.id >+ @template_id = "00000000-0000-0000-0000-000000000000" > name = 'vm-'+Time.now.to_i.to_s >- @vm = @client.create_vm(:name => name, :template => @blank_template_id, :cluster => @cluster) >+ @vm = @client.create_vm(:name => name, :template => @template_id, :cluster => @cluster) > @client.add_volume(@vm.id) >- @client.add_interface(@vm.id) >+ @client.add_interface(@vm.id, :network_name => 'rhevm') > while !@client.vm(@vm.id).ready? do > end > end >@@ -71,8 +71,9 @@ end > describe "Admin API VM Life cycle" do > > before(:all) do >- user, password, url = endpoint >- @client = ::OVIRT::Client.new(user, password, url, nil, nil, false) >+ user, password, url, datacenter = endpoint >+ opts = {:datacenter_id => datacenter, :ca_cert_file => "#{File.dirname(__FILE__)}/../ca_cert.pem"} >+ @client = ::OVIRT::Client.new(user, password, url, opts) > end > > context 'admin basic vm and templates operations' do >@@ -83,8 +84,11 @@ end > describe "User API VM Life cycle" do > > before(:all) do >- user, password, url = endpoint >- @client = ::OVIRT::Client.new(user, password, url, nil, nil, support_user_level_api) >+ user, password, url, datacenter = endpoint >+ opts = {:datacenter_id => datacenter, >+ :ca_cert_file => "#{File.dirname(__FILE__)}/../ca_cert.pem", >+ :filtered_api => support_user_level_api} >+ @client = ::OVIRT::Client.new(user, password, url, opts) > end > > context 'user basic vm and templates operations' do >diff --git a/spec/lib/endpoint.rb b/spec/lib/endpoint.rb >index c85fbd1..e1f8e34 100644 >--- a/spec/lib/endpoint.rb >+++ b/spec/lib/endpoint.rb >@@ -3,12 +3,7 @@ module OVIRT::RSpec::Endpoint > def endpoint > file = File.expand_path("../endpoint.yml", File.dirname(__FILE__)) > @endpoint ||= YAML.load(File.read(file)) >- user = @endpoint['user'] >- password= @endpoint['password'] >- hostname = @endpoint['hostname'] >- port = @endpoint['port'] >- url = "http://#{hostname}:#{port}/api" >- return user, password, url >+ return @endpoint['user'], @endpoint['password'], @endpoint['url'] , @endpoint['datacenter'] > end > > def support_user_level_api >diff --git a/spec/unit/client_spec.rb b/spec/unit/client_spec.rb >index c4fd7da..1b6a13e 100644 >--- a/spec/unit/client_spec.rb >+++ b/spec/unit/client_spec.rb >@@ -1,6 +1,27 @@ > require "#{File.dirname(__FILE__)}/../spec_helper" > > describe OVIRT::Client do >+ context 'client initialization' do >+ it 'should accept no option' do >+ OVIRT::Client::new('mockuser','mockpass','http://example.com/api') >+ end >+ >+ it 'should accept no datacenter_id in options' do >+ OVIRT::Client::new('mockuser','mockpass','http://example.com/api', :datacenter_id => '123123') >+ end >+ >+ it 'should support backward compatibility' do >+ OVIRT::Client::new('mockuser','mockpass','http://example.com/api', '123123', '123123', false) >+ end >+ >+ it 'should support options hash in 4th parameter' do >+ OVIRT::Client::new('mockuser','mockpass','http://example.com/api', >+ {:datacenter_id => '123123', >+ :cluster_id => '123123', >+ :filtered_api => false, >+ :ca_cert_file => 'ca_cert.pem'}) >+ end >+ end > > context 'http comms' do > before(:each) do >-- >1.8.3.1 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 1058595
:
866995
|
869621