rubysspi 1.2.4 → 1.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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