rubysspi 1.2.4 → 1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,10 @@
1
+ == 1.3
2
+ * Updated library to work with either "Negotiate" or "NTLM" authorization schemes. Arguments to Win32::SSPI.get_initial_token have changed
3
+ but that should only impact code directly using the library. Net::HTTP support still works the same.
4
+
5
+ == 1.2.5
6
+ * Fixed patching on net/http so hard-coded paths are not used, but paths from rbconfig.
7
+
1
8
  == 1.2.4
2
9
  * Compatibility updates for rubygems 1.2.0
3
10
 
data/Rakefile CHANGED
@@ -6,7 +6,7 @@ require 'rake/testtask'
6
6
  spec = Gem::Specification.new do |s|
7
7
  s.name = "rubysspi"
8
8
  s.summary = "A library which implements Ruby bindings to the Win32 SSPI library. Also includes a module to add Negotiate authentication support to Net::HTTP."
9
- s.version = "1.2.4"
9
+ s.version = "1.3"
10
10
  s.author = "Justin Bailey"
11
11
  s.email = "jgbailey @nospam@ gmail.com"
12
12
  s.homepage = "http://rubyforge.org/projects/rubysspi/"
@@ -62,20 +62,21 @@ unless spec
62
62
  exit
63
63
  end
64
64
 
65
- gem_path = Pathname.new(spec.full_gem_path) + "lib"
65
+ gem_path = (Pathname.new(spec.full_gem_path) + "lib").sub(Config::TOPDIR, "\#{Config::TOPDIR}")
66
66
 
67
67
  # Write patch file.
68
68
  puts "Creating patch file to replace #{orig_file}"
69
69
  orig_file.open("w") { |f| f.write(<<EOS) }
70
70
  # Include original net/http
71
71
  require 'net/#{orig_dest.basename(orig_dest.extname)}'
72
+ require 'rbconfig'
72
73
 
73
74
  # This magic constant can be defined to disable the patch.
74
75
  unless defined? DISABLE_RUBY_SSPI_PATCH
75
76
  # Because rubygems >= 0.9.2 requires net/http,
76
77
  # we can't depend on ruby gems here. Instead, directly
77
78
  # require path containing RubySSPI gem.
78
- $: << "#{gem_path}" unless $:.include?("#{gem_path}")
79
+ $: << %(#{gem_path}) unless $:.include?(%(#{gem_path}))
79
80
  require 'win32/sspi/http_proxy_patch'
80
81
  end
81
82
  EOS
@@ -224,9 +224,14 @@ module Win32
224
224
  raise "http must respond to :get" unless http.respond_to?(:get)
225
225
  nego_auth = self.new user, domain
226
226
 
227
- resp = http.get path, { "Proxy-Authorization" => "Negotiate " + nego_auth.get_initial_token }
228
- if resp["Proxy-Authenticate"]
227
+ resp = http.get path, { "Proxy-Authorization" => "Negotiate " + nego_auth.get_initial_token("Negotiate") }
228
+ # Negotiate may not be supported, so we need to look for NTLM too.
229
+
230
+ if resp["Proxy-Authenticate"].include? "Negotiate"
229
231
  resp = http.get path, { "Proxy-Authorization" => "Negotiate " + nego_auth.complete_authentication(resp["Proxy-Authenticate"].split(" ").last.strip) }
232
+ elsif resp["Proxy-Authenticate"].include? "NTLM"
233
+ resp = http.get path, { "Proxy-Authorization" => "NTLM " + nego_auth.get_initial_token("NTLM") }
234
+ resp = http.get path, { "Proxy-Authorization" => "NTLM " + nego_auth.complete_authentication(resp["Proxy-Authenticate"].split(" ").last.strip) }
230
235
  end
231
236
 
232
237
  resp
@@ -247,9 +252,11 @@ module Win32
247
252
 
248
253
  # Gets the initial Negotiate token. Returns it as a base64 encoded string suitable for use in HTTP. Can
249
254
  # be easily decoded, however.
250
- def get_initial_token
255
+ #
256
+ # auth_type is the authentication method being used. It is usually "Negotiate" or "NTLM".
257
+ def get_initial_token(auth_type)
251
258
  raise "This object is no longer usable because its resources have been freed." if @cleaned_up
252
- get_credentials
259
+ get_credentials auth_type
253
260
 
254
261
  outputBuffer = SecurityBuffer.new
255
262
  @context = CtxtHandle.new
@@ -275,7 +282,7 @@ module Win32
275
282
  # Nil token OK, just set it to empty string
276
283
  token = "" if token.nil?
277
284
 
278
- if token.include? "Negotiate"
285
+ if token.include?("Negotiate") || token.include?("NTLM")
279
286
  # If the Negotiate prefix is passed in, assume we are seeing "Negotiate <token>" and get the token.
280
287
  token = token.split(" ").last
281
288
  end
@@ -314,11 +321,13 @@ module Win32
314
321
  end
315
322
 
316
323
  # Gets credentials based on user, domain or both. If both are nil, an error occurs
317
- def get_credentials
324
+ #
325
+ # auth_type is the authentication type being used. It usually either "Negotiate" or "NTLM".
326
+ def get_credentials(auth_type)
318
327
  @credentials = CredHandle.new
319
328
  ts = TimeStamp.new
320
329
  @identity = Identity.new @user, @domain
321
- result = SSPIResult.new(API::AcquireCredentialsHandle.call(nil, "Negotiate", SECPKG_CRED_OUTBOUND, nil, @identity.to_p,
330
+ result = SSPIResult.new(API::AcquireCredentialsHandle.call(nil, auth_type, SECPKG_CRED_OUTBOUND, nil, @identity.to_p,
322
331
  nil, nil, @credentials.to_p, ts.to_p))
323
332
  raise "Error acquire credentials: #{result}" unless result.ok?
324
333
  end
@@ -78,10 +78,10 @@ module Net
78
78
  end_transport req, res
79
79
  begin_transport req
80
80
  if proxy?
81
- req["Proxy-Authorization"] = "#{tok} #{n.get_initial_token}"
81
+ req["Proxy-Authorization"] = "#{tok} #{n.get_initial_token(tok)}"
82
82
  req["Proxy-Connection"] = "Keep-Alive"
83
83
  else
84
- req["Authorization"] = "#{tok} #{n.get_initial_token}"
84
+ req["Authorization"] = "#{tok} #{n.get_initial_token(tok)}"
85
85
  end
86
86
  # Some versions of ISA will close the connection if this isn't present.
87
87
  req["Connection"] = "Keep-Alive"
@@ -32,8 +32,16 @@ class NTLMTest < Test::Unit::TestCase
32
32
 
33
33
  Net::HTTP.Proxy(proxy.host, proxy.port).start("www.google.com") do |http|
34
34
  nego_auth = Win32::SSPI::NegotiateAuth.new
35
- sr = http.request_get "/", { "Proxy-Authorization" => "Negotiate " + nego_auth.get_initial_token }
36
- resp = http.get "/", { "Proxy-Authorization" => "Negotiate " + nego_auth.complete_authentication(sr["Proxy-Authenticate"].split(" ").last.strip) }
35
+ sr = http.request_get "/", { "Proxy-Authorization" => "Negotiate " + nego_auth.get_initial_token("Negotiate") }
36
+ if sr["Proxy-Authenticate"].include? "Negotiate"
37
+ resp = http.get "/", { "Proxy-Authorization" => "Negotiate " + nego_auth.complete_authentication(sr["Proxy-Authenticate"].split(" ").last.strip) }
38
+ elsif sr["Proxy-Authenticate"].include? "NTLM"
39
+ sr = http.get "/", { "Proxy-Authorization" => "NTLM " + nego_auth.get_initial_token("NTLM") }
40
+ resp = http.get "/", { "Proxy-Authorization" => "NTLM " + nego_auth.complete_authentication(sr["Proxy-Authenticate"].split(" ").last.strip) }
41
+ else
42
+ raise "Proxy-Authentica method must be either NTLM or Negotiate. Got #{sr["Proxy-Authenticate"].inspect}"
43
+ end
44
+
37
45
  # Google redirects to country of origins domain if not US.
38
46
  assert success_or_redirect(resp.code), "Response code not as expected: #{resp.inspect}"
39
47
  resp = http.get "/foobar.html"
@@ -56,8 +64,17 @@ class NTLMTest < Test::Unit::TestCase
56
64
 
57
65
  Net::HTTP.Proxy(proxy.host, proxy.port).start("www.google.com") do |http|
58
66
  nego_auth = Win32::SSPI::NegotiateAuth.new
59
- sr = http.request_get "/", { "Proxy-Authorization" => "Negotiate " + nego_auth.get_initial_token }
60
- resp = http.get "/", { "Proxy-Authorization" => "Negotiate " + nego_auth.complete_authentication(sr["Proxy-Authenticate"].split(" ").last.strip) }
67
+ sr = http.request_get "/", { "Proxy-Authorization" => "Negotiate " + nego_auth.get_initial_token("Negotiate") }
68
+
69
+ if sr["Proxy-Authenticate"].include? "Negotiate"
70
+ resp = http.get "/", { "Proxy-Authorization" => "Negotiate " + nego_auth.complete_authentication(sr["Proxy-Authenticate"].split(" ").last.strip) }
71
+ elsif sr["Proxy-Authenticate"].include? "NTLM"
72
+ sr = http.get "/", { "Proxy-Authorization" => "NTLM " + nego_auth.get_initial_token("NTLM") }
73
+ resp = http.get "/", { "Proxy-Authorization" => "NTLM " + nego_auth.complete_authentication(sr["Proxy-Authenticate"].split(" ").last.strip) }
74
+ else
75
+ raise "Proxy-Authentica method must be either NTLM or Negotiate. Got #{sr["Proxy-Authenticate"].inspect}"
76
+ end
77
+
61
78
  assert success_or_redirect(resp.code), "Response code not as expected: #{resp.inspect}"
62
79
  assert_raises(RuntimeError, "Should not be able to call complete_authentication again") do
63
80
  nego_auth.complete_authentication "foo"
@@ -71,19 +88,38 @@ class NTLMTest < Test::Unit::TestCase
71
88
  # Test that raw token works
72
89
  Net::HTTP.Proxy(proxy.host, proxy.port).start("www.google.com") do |http|
73
90
  nego_auth = Win32::SSPI::NegotiateAuth.new
74
- sr = http.request_get "/", { "Proxy-Authorization" => "Negotiate " + nego_auth.get_initial_token }
75
- token = Base64.decode64(sr["Proxy-Authenticate"].split(" ").last.strip)
76
- completed_token = nego_auth.complete_authentication(token)
77
- resp = http.get "/", { "Proxy-Authorization" => "Negotiate " + completed_token }
78
- assert success_or_redirect(resp.code), "Response code not as expected: #{resp.inspect}"
91
+ sr = http.request_get "/", { "Proxy-Authorization" => "Negotiate " + nego_auth.get_initial_token("Negotiate") }
92
+
93
+ if sr["Proxy-Authenticate"].include? "Negotiate"
94
+ token = Base64.decode64(sr["Proxy-Authenticate"].split(" ").last.strip)
95
+ completed_token = nego_auth.complete_authentication(token)
96
+ resp = http.get "/", { "Proxy-Authorization" => "Negotiate " + completed_token }
97
+ assert success_or_redirect(resp.code), "Response code not as expected: #{resp.inspect}"
98
+ elsif sr["Proxy-Authenticate"].include? "NTLM"
99
+ sr = http.request_get "/", { "Proxy-Authorization" => "NTLM " + nego_auth.get_initial_token("NTLM") }
100
+ token = Base64.decode64(sr["Proxy-Authenticate"].split(" ").last.strip)
101
+ completed_token = nego_auth.complete_authentication(token)
102
+ resp = http.get "/", { "Proxy-Authorization" => "NTLM " + completed_token }
103
+ assert success_or_redirect(resp.code), "Response code not as expected: #{resp.inspect}"
104
+ else
105
+ raise "Proxy-Authentica method must be either NTLM or Negotiate. Got #{sr["Proxy-Authenticate"].inspect}"
106
+ end
79
107
  end
80
108
 
81
109
  # Test that token w/ "Negotiate" header included works
82
110
  Net::HTTP.Proxy(proxy.host, proxy.port).start("www.google.com") do |http|
83
111
  nego_auth = Win32::SSPI::NegotiateAuth.new
84
- sr = http.request_get "/", { "Proxy-Authorization" => "Negotiate " + nego_auth.get_initial_token }
85
- resp = http.get "/", { "Proxy-Authorization" => "Negotiate " + nego_auth.complete_authentication(sr["Proxy-Authenticate"]) }
86
- assert success_or_redirect(resp.code), "Response code not as expected: #{resp.inspect}"
112
+ sr = http.request_get "/", { "Proxy-Authorization" => "Negotiate " + nego_auth.get_initial_token("Negotiate") }
113
+ if sr["Proxy-Authenticate"].include? "Negotiate"
114
+ resp = http.get "/", { "Proxy-Authorization" => "Negotiate " + nego_auth.complete_authentication(sr["Proxy-Authenticate"]) }
115
+ assert success_or_redirect(resp.code), "Response code not as expected: #{resp.inspect}"
116
+ elsif sr["Proxy-Authenticate"].include? "NTLM"
117
+ sr = http.request_get "/", { "Proxy-Authorization" => "NTLM " + nego_auth.get_initial_token("NTLM") }
118
+ resp = http.get "/", { "Proxy-Authorization" => "NTLM " + nego_auth.complete_authentication(sr["Proxy-Authenticate"]) }
119
+ assert success_or_redirect(resp.code), "Response code not as expected: #{resp.inspect}"
120
+ else
121
+ raise "Proxy-Authentica method must be either NTLM or Negotiate. Got #{sr["Proxy-Authenticate"].inspect}"
122
+ end
87
123
  end
88
124
  end
89
125
 
@@ -29,8 +29,14 @@ conn = Net::HTTP.Proxy(proxy.host, proxy.port).new("www.google.com")
29
29
  conn.set_debug_output $stdout
30
30
  conn.start() do |http|
31
31
  nego_auth = Win32::SSPI::NegotiateAuth.new
32
- sr = http.request_get "/", { "Proxy-Authorization" => "Negotiate " + nego_auth.get_initial_token }
33
- resp = http.get "/", { "Proxy-Authorization" => "Negotiate " + nego_auth.complete_authentication(sr["Proxy-Authenticate"].split(" ").last.strip) }
32
+ sr = http.request_get "/", { "Proxy-Authorization" => "Negotiate " + nego_auth.get_initial_token("Negotiate") }
33
+ if sr["Proxy-Authenticate"].include? "Negotiate"
34
+ resp = http.get "/", { "Proxy-Authorization" => "Negotiate " + nego_auth.complete_authentication(sr["Proxy-Authenticate"].split(" ").last.strip) }
35
+ elsif sr["Proxy-Authenticate"].include? "NTLM"
36
+ sr = http.request_get "/", { "Proxy-Authorization" => "NTLM " + nego_auth.get_initial_token("NTLM") }
37
+ resp = http.get "/", { "Proxy-Authorization" => "NTLM " + nego_auth.complete_authentication(sr["Proxy-Authenticate"].split(" ").last.strip) }
38
+ end
39
+
34
40
  # Google redirects to country of origins domain if not US.
35
41
  raise "Response code not as expected: #{resp.inspect}" unless resp.code.to_i == 200 || resp.code.to_i == 302
36
42
  resp = http.get "/foobar.html"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubysspi
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.4
4
+ version: "1.3"
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Bailey
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-08-01 00:00:00 -07:00
12
+ date: 2008-12-08 00:00:00 -08:00
13
13
  default_executable:
14
14
  dependencies: []
15
15