pingpp 2.0.8 → 2.0.11

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,3 @@
1
1
  module Pingpp
2
- VERSION = '2.0.8'
2
+ VERSION = '2.0.11'
3
3
  end
data/lib/pingpp.rb CHANGED
@@ -3,8 +3,9 @@
3
3
  require 'cgi'
4
4
  require 'set'
5
5
  require 'openssl'
6
- require 'rest_client'
6
+ require 'rest-client'
7
7
  require 'json'
8
+ require 'base64'
8
9
 
9
10
  # Version
10
11
  require 'pingpp/version'
@@ -21,7 +22,6 @@ require 'pingpp/pingpp_object'
21
22
  require 'pingpp/api_resource'
22
23
  require 'pingpp/singleton_api_resource'
23
24
  require 'pingpp/list_object'
24
- require 'pingpp/certificate_blacklist'
25
25
  require 'pingpp/charge'
26
26
  require 'pingpp/refund'
27
27
  require 'pingpp/red_envelope'
@@ -43,16 +43,15 @@ module Pingpp
43
43
  DEFAULT_CA_BUNDLE_PATH = File.dirname(__FILE__) + '/data/ca-certificates.crt'
44
44
  @api_base = 'https://api.pingxx.com'
45
45
 
46
- @api_version = '2015-06-03'
46
+ @api_version = '2015-10-10'
47
47
 
48
48
  @ssl_bundle_path = DEFAULT_CA_BUNDLE_PATH
49
49
  @verify_ssl_certs = true
50
- @CERTIFICATE_VERIFIED = false
51
50
 
52
51
  HEADERS_TO_PARSE = [:pingpp_one_version, :pingpp_sdk_version]
53
52
 
54
53
  class << self
55
- attr_accessor :api_key, :api_base, :verify_ssl_certs, :api_version, :parsed_headers
54
+ attr_accessor :api_key, :api_base, :verify_ssl_certs, :api_version, :parsed_headers, :private_key_path
56
55
  end
57
56
 
58
57
  def self.api_url(url='')
@@ -92,15 +91,19 @@ module Pingpp
92
91
  'email support@pingxx.com if you have any questions.)')
93
92
  end
94
93
 
95
- request_opts = { :verify_ssl => false, :ssl_version => 'TLSv1' }
96
-
97
- if ssl_preflight_passed?
98
- request_opts.update(:verify_ssl => OpenSSL::SSL::VERIFY_PEER,
99
- :ssl_ca_file => @ssl_bundle_path)
100
- end
101
-
102
- if @verify_ssl_certs and !@CERTIFICATE_VERIFIED
103
- @CERTIFICATE_VERIFIED = CertificateBlacklist.check_ssl_cert(@api_base, @ssl_bundle_path)
94
+ if verify_ssl_certs
95
+ request_opts = {:verify_ssl => OpenSSL::SSL::VERIFY_PEER,
96
+ :ssl_ca_file => @ssl_bundle_path,
97
+ :ssl_version => 'TLSv1'}
98
+ else
99
+ request_opts = {:verify_ssl => false,
100
+ :ssl_version => 'TLSv1'}
101
+ unless @verify_ssl_warned
102
+ @verify_ssl_warned = true
103
+ $stderr.puts("WARNING: Running without SSL cert verification. " \
104
+ "You should never do this in production. " \
105
+ "Execute 'Pingpp.verify_ssl_certs = true' to enable verification.")
106
+ end
104
107
  end
105
108
 
106
109
  params = Util.objects_to_ids(params)
@@ -115,7 +118,7 @@ module Pingpp
115
118
  payload = JSON.generate(params)
116
119
  end
117
120
 
118
- request_opts.update(:headers => request_headers(api_key, method.to_s.downcase.to_sym == :post).update(headers),
121
+ request_opts.update(:headers => request_headers(api_key, method.to_s.downcase.to_sym == :post, payload).update(headers),
119
122
  :method => method, :open_timeout => 30,
120
123
  :payload => payload, :url => url, :timeout => 80)
121
124
 
@@ -146,23 +149,6 @@ module Pingpp
146
149
 
147
150
  private
148
151
 
149
- def self.ssl_preflight_passed?
150
- if !verify_ssl_certs && !@no_verify
151
- $stderr.puts "WARNING: Running without SSL cert verification. " +
152
- "Execute 'Pingpp.verify_ssl_certs = true' to enable verification."
153
-
154
- @no_verify = true
155
-
156
- elsif !Util.file_readable(@ssl_bundle_path) && !@no_bundle
157
- $stderr.puts "WARNING: Running without SSL cert verification " +
158
- "because #{@ssl_bundle_path} isn't readable"
159
-
160
- @no_bundle = true
161
- end
162
-
163
- !(@no_verify || @no_bundle)
164
- end
165
-
166
152
  def self.user_agent
167
153
  @uname ||= get_uname
168
154
  lang_version = "#{RUBY_VERSION} p#{RUBY_PATCHLEVEL} (#{RUBY_RELEASE_DATE})"
@@ -189,7 +175,7 @@ module Pingpp
189
175
  map { |k,v| "#{k}=#{Util.url_encode(v)}" }.join('&')
190
176
  end
191
177
 
192
- def self.request_headers(api_key, is_post=false)
178
+ def self.request_headers(api_key, is_post=false, data=nil)
193
179
  headers = {
194
180
  :user_agent => "Pingpp/v1 RubyBindings/#{Pingpp::VERSION}",
195
181
  :authorization => "Bearer #{api_key}",
@@ -205,6 +191,13 @@ module Pingpp
205
191
  headers.update(:x_pingpp_client_raw_user_agent => user_agent.inspect,
206
192
  :error => "#{e} (#{e.class})")
207
193
  end
194
+
195
+ if is_post && private_key_path && data
196
+ signature = sign_request(data, private_key_path)
197
+ headers.update(:pingplusplus_signature => signature)
198
+ end
199
+
200
+ headers
208
201
  end
209
202
 
210
203
  def self.execute_request(opts)
@@ -223,6 +216,11 @@ module Pingpp
223
216
  Util.symbolize_names(response)
224
217
  end
225
218
 
219
+ def self.sign_request(data, key_path)
220
+ pkey = OpenSSL::PKey.read(File.read(key_path))
221
+ return Base64.strict_encode64(pkey.sign(OpenSSL::Digest::SHA256.new, data))
222
+ end
223
+
226
224
  def self.general_api_error(rcode, rbody)
227
225
  APIError.new("Invalid response object from API: #{rbody.inspect} " +
228
226
  "(HTTP response code was #{rcode})", rcode, rbody)
@@ -271,7 +269,7 @@ module Pingpp
271
269
  def self.handle_restclient_error(e)
272
270
  connection_message = "Please check your internet connection and try again. " \
273
271
  "If this problem persists, you should check Pingpp's service status at " \
274
- "https://pingxx.com, or let us know at support@pingxx.com."
272
+ "https://www.pingxx.com/status"
275
273
 
276
274
  case e
277
275
  when RestClient::RequestTimeout
@@ -284,8 +282,7 @@ module Pingpp
284
282
  when RestClient::SSLCertificateNotVerified
285
283
  message = "Could not verify Pingpp's SSL certificate. " \
286
284
  "Please make sure that your network is not intercepting certificates. " \
287
- "(Try going to (#{@api_base}) in your browser.) " \
288
- "If this problem persists, let us know at support@pingxx.com."
285
+ "(Try going to (#{@api_base}) in your browser.)"
289
286
 
290
287
  when SocketError
291
288
  message = "Unexpected error communicating when trying to connect to Pingpp. " \
@@ -293,8 +290,7 @@ module Pingpp
293
290
  "To check, try running 'host pingxx.com' from the command line."
294
291
 
295
292
  else
296
- message = "Unexpected error communicating with Pingpp. " \
297
- "If this problem persists, let us know at support@pingxx.com."
293
+ message = "Unexpected error communicating with Pingpp."
298
294
 
299
295
  end
300
296
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pingpp
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.8
4
+ version: 2.0.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - Xufeng Weng
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-07-13 00:00:00.000000000 Z
11
+ date: 2016-03-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rest-client
@@ -141,7 +141,6 @@ files:
141
141
  - lib/pingpp/api_operations/list.rb
142
142
  - lib/pingpp/api_operations/update.rb
143
143
  - lib/pingpp/api_resource.rb
144
- - lib/pingpp/certificate_blacklist.rb
145
144
  - lib/pingpp/charge.rb
146
145
  - lib/pingpp/errors/api_connection_error.rb
147
146
  - lib/pingpp/errors/api_error.rb
@@ -1,51 +0,0 @@
1
- require 'uri'
2
- require 'digest/sha1'
3
-
4
- module Pingpp
5
- module CertificateBlacklist
6
-
7
- BLACKLIST = {
8
- "api.pingxx.com" => [
9
- ]
10
- }
11
-
12
- # Preflight the SSL certificate presented by the backend. This isn't 100%
13
- # bulletproof, in that we're not actually validating the transport used to
14
- # communicate with Pingpp, merely that the first attempt to does not use a
15
- # revoked certificate.
16
-
17
- # Unfortunately the interface to OpenSSL doesn't make it easy to check the
18
- # certificate before sending potentially sensitive data on the wire. This
19
- # approach raises the bar for an attacker significantly.
20
-
21
- def self.check_ssl_cert(uri, ca_file)
22
- uri = URI.parse(uri)
23
-
24
- sock = TCPSocket.new(uri.host, uri.port)
25
- ctx = OpenSSL::SSL::SSLContext.new
26
- ctx.set_params(:verify_mode => OpenSSL::SSL::VERIFY_PEER,
27
- :ca_file => ca_file)
28
-
29
- socket = OpenSSL::SSL::SSLSocket.new(sock, ctx)
30
- socket.connect
31
-
32
- certificate = socket.peer_cert.to_der
33
- fingerprint = Digest::SHA1.hexdigest(certificate)
34
-
35
- if blacklisted_certs = BLACKLIST[uri.host]
36
- if blacklisted_certs.include?(fingerprint)
37
- raise APIConnectionError.new(
38
- "Invalid server certificate. You tried to connect to a server that" +
39
- "has a revoked SSL certificate, which means we cannot securely send" +
40
- "data to that server. Please email support@pingxx.com if you need" +
41
- "help connecting to the correct API server."
42
- )
43
- end
44
- end
45
-
46
- socket.close
47
-
48
- return true
49
- end
50
- end
51
- end