net-ssh-kerberos 0.1.3 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +33 -4
- data/VERSION.yml +2 -2
- data/lib/net/ssh/authentication/methods/gssapi_with_mic.rb +5 -8
- data/lib/net/ssh/kerberos.rb +7 -20
- data/lib/net/ssh/kerberos/constants.rb +3 -7
- data/lib/net/ssh/kerberos/context.rb +75 -0
- data/lib/net/ssh/kerberos/drivers.rb +57 -0
- data/lib/net/ssh/kerberos/drivers/gss.rb +263 -0
- data/lib/net/ssh/kerberos/drivers/sspi.rb +216 -0
- data/test/gss_context_test.rb +3 -4
- data/test/gss_test.rb +43 -61
- data/test/sspi_context_test.rb +2 -4
- data/test/sspi_test.rb +31 -39
- metadata +7 -20
- data/lib/net/ssh/kerberos/common/context.rb +0 -71
- data/lib/net/ssh/kerberos/gss.rb +0 -9
- data/lib/net/ssh/kerberos/gss/api.rb +0 -163
- data/lib/net/ssh/kerberos/gss/context.rb +0 -115
- data/lib/net/ssh/kerberos/sspi.rb +0 -5
- data/lib/net/ssh/kerberos/sspi/api.rb +0 -228
- data/lib/net/ssh/kerberos/sspi/context.rb +0 -76
@@ -0,0 +1,216 @@
|
|
1
|
+
module Net; module SSH; module Kerberos; module Drivers
|
2
|
+
|
3
|
+
module SSPI
|
4
|
+
|
5
|
+
SEC_E_OK = 0x00000000
|
6
|
+
|
7
|
+
SEC_I_CONTINUE_NEEDED = 0x00090312
|
8
|
+
SEC_I_COMPLETE_NEEDED = 0x00090313
|
9
|
+
SEC_I_COMPLETE_AND_CONTINUE = 0x00090314
|
10
|
+
SEC_I_INCOMPLETE_CREDENTIALS = 0x00090320
|
11
|
+
SEC_I_RENEGOTIATE = 0x00090321
|
12
|
+
|
13
|
+
SEC_E_INSUFFICIENT_MEMORY = 0x80090300
|
14
|
+
SEC_E_INVALID_HANDLE = 0x80090301
|
15
|
+
SEC_E_UNSUPPORTED_FUNCTION = 0x80090302
|
16
|
+
SEC_E_TARGET_UNKNOWN = 0x80090303
|
17
|
+
SEC_E_INTERNAL_ERROR = 0x80090304
|
18
|
+
SEC_E_SECPKG_NOT_FOUND = 0x80090305
|
19
|
+
SEC_E_NOT_OWNER = 0x80090306
|
20
|
+
SEC_E_INVALID_TOKEN = 0x80090308
|
21
|
+
SEC_E_LOGON_DENIED = 0x8009030C
|
22
|
+
SEC_E_UNKNOWN_CREDENTIALS = 0x8009030D
|
23
|
+
SEC_E_NO_CREDENTIALS = 0x8009030E
|
24
|
+
SEC_E_NO_AUTHENTICATING_AUTHORITY = 0x80090311
|
25
|
+
SEC_E_WRONG_PRINCIPAL = 0x80090322
|
26
|
+
|
27
|
+
SECPKG_CRED_INBOUND = 0x00000001
|
28
|
+
SECPKG_CRED_OUTBOUND = 0x00000002
|
29
|
+
SECPKG_CRED_BOTH = 0x00000003
|
30
|
+
|
31
|
+
SECBUFFER_EMPTY = 0
|
32
|
+
SECBUFFER_DATA = 1
|
33
|
+
SECBUFFER_TOKEN = 2
|
34
|
+
|
35
|
+
SECURITY_NATIVE_DREP = 0x00000010
|
36
|
+
SECURITY_NETWORK_DREP = 0x00000000
|
37
|
+
|
38
|
+
SECPKG_ATTR_SIZES = 0
|
39
|
+
SECPKG_ATTR_NAMES = 1
|
40
|
+
|
41
|
+
ISC_REQ_DELEGATE = 0x00000001
|
42
|
+
ISC_REQ_MUTUAL_AUTH = 0x00000002
|
43
|
+
ISC_REQ_INTEGRITY = 0x00010000
|
44
|
+
|
45
|
+
module API
|
46
|
+
extend DL::Importable
|
47
|
+
include DLExtensions
|
48
|
+
|
49
|
+
dlload 'secur32'
|
50
|
+
|
51
|
+
typealias "void **", "p", PTR_REF_ENC, proc{|v| v.ptr}
|
52
|
+
typealias "SECURITY_STATUS", "L", proc{|v| v.to_i }, proc{|v| SSPIResult.new(v) }
|
53
|
+
typealias "USHORT", "unsigned short"
|
54
|
+
typealias "ULONG_REF", "unsigned long ref"
|
55
|
+
typealias "SEC_CHAR *", "char *"
|
56
|
+
typealias "PCtxtBuffer", "void **"
|
57
|
+
typealias "PCharBuffer", "P", nil, nil, "P", PTR_ENC
|
58
|
+
SecPkgInfo = struct [ "ULONG capabilities", "USHORT version", "USHORT rpcid",
|
59
|
+
"ULONG max_token", "SEC_CHAR *name", "SEC_CHAR *comment" ]
|
60
|
+
typealias "PSecPkgInfo", "p", PTR_REF_ENC, PTR_REF_DEC(SecPkgInfo)
|
61
|
+
SecHandle = struct2([ "ULONG lower", "ULONG upper" ]) do def nil?; lower.zero? && upper.zero? end end
|
62
|
+
typealias "PSecHandle", "P"
|
63
|
+
typealias "PCredHandle", "PSecHandle"
|
64
|
+
typealias "PCtxtHandle", "PSecHandle"
|
65
|
+
SecBuffer = struct2 [ "ULONG length", "ULONG type", "PCharBuffer data" ] do
|
66
|
+
def to_s; data.to_s(length) end
|
67
|
+
end
|
68
|
+
typealias "PSecBuffer", "P"
|
69
|
+
SecBufferDesc = struct2 [ "ULONG version", "ULONG count", "PSecBuffer buffers" ] do
|
70
|
+
def buffer(n) SecBuffer.new(@ptr[:buffers] + SecBuffer.size * n) end
|
71
|
+
end
|
72
|
+
typealias "PSecBufferDesc", "P"
|
73
|
+
TimeStamp = SecHandle
|
74
|
+
typealias "PTimeStamp", "P"
|
75
|
+
SecPkgSizes = struct [ "ULONG max_token", "ULONG max_signature",
|
76
|
+
"ULONG block_size", "ULONG security_trailer" ]
|
77
|
+
|
78
|
+
class SSPIResult
|
79
|
+
@@map = {}
|
80
|
+
SSPI.constants.each { |v| @@map[SSPI.const_get(v.to_s)] = v if v.to_s =~ /^SEC_[EI]_/ }
|
81
|
+
|
82
|
+
attr_reader :value
|
83
|
+
alias :to_i :value
|
84
|
+
|
85
|
+
def initialize(value)
|
86
|
+
value = [value].pack("L").unpack("L").first
|
87
|
+
raise "#{value.to_s(16)} is not a recognized result" unless @@map.has_key? value
|
88
|
+
@value = value
|
89
|
+
end
|
90
|
+
|
91
|
+
def ok?; value & 0x80000000 == 0 end
|
92
|
+
def complete?; value == 0 end
|
93
|
+
def incomplete?; SEC_I_COMPLETE_NEEDED==value || SEC_I_COMPLETE_AND_CONTINUE==value end
|
94
|
+
def failure?; value & 0x80000000 != 0 end
|
95
|
+
def temporary_failure?
|
96
|
+
value==SEC_E_LOGON_DENIED || value==SEC_E_NO_AUTHENTICATING_AUTHORITY || value==SEC_E_NO_CREDENTIALS
|
97
|
+
end
|
98
|
+
def to_s; @@map[@value].to_s end
|
99
|
+
def ==(result)
|
100
|
+
case result
|
101
|
+
when SSPIResult; @value == result.value
|
102
|
+
when Fixnum; @value == @@map[other]
|
103
|
+
else false
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
extern 'SECURITY_STATUS FreeContextBuffer(void *)'
|
109
|
+
extern 'SECURITY_STATUS QuerySecurityPackageInfo(SEC_CHAR *, PSecPkgInfo)'
|
110
|
+
extern 'SECURITY_STATUS AcquireCredentialsHandle(void *, SEC_CHAR *, ULONG, void *, '+
|
111
|
+
'void *, void *, void *, PCredHandle, PTimeStamp)'
|
112
|
+
extern 'SECURITY_STATUS QueryCredentialsAttributes(PCredHandle, ULONG, PCtxtBuffer)'
|
113
|
+
extern 'SECURITY_STATUS FreeCredentialsHandle(PCredHandle)'
|
114
|
+
extern 'SECURITY_STATUS QueryContextAttributes(PCtxtHandle, ULONG, void *)'
|
115
|
+
extern 'SECURITY_STATUS CompleteAuthToken(PCtxtHandle, PSecBufferDesc)'
|
116
|
+
extern 'SECURITY_STATUS MakeSignature(PCtxtHandle, ULONG, PSecBufferDesc, ULONG)'
|
117
|
+
extern 'SECURITY_STATUS InitializeSecurityContext(PCredHandle, PCtxtHandle, char *, '+
|
118
|
+
'ULONG, ULONG, ULONG, PSecBufferDesc, ULONG, PCtxtHandle, '+
|
119
|
+
'PSecBufferDesc, ULONG_REF, PTimeStamp)'
|
120
|
+
extern 'SECURITY_STATUS DeleteSecurityContext(PCtxtHandle)'
|
121
|
+
|
122
|
+
def SecBuffer.createArray(types,data)
|
123
|
+
buffs = []
|
124
|
+
mem = DL::malloc(size * types.size)
|
125
|
+
0.upto(types.size - 1) do |n|
|
126
|
+
buff = new DL::PtrData.new(mem.to_i + (n * size), size)
|
127
|
+
buff.type = types[n]
|
128
|
+
n = data[n]
|
129
|
+
buff.data = Fixnum===n ? "\0" * n : n
|
130
|
+
buff.length = Fixnum===n ? n : n.length
|
131
|
+
buffs << buff
|
132
|
+
end
|
133
|
+
buffs
|
134
|
+
end
|
135
|
+
|
136
|
+
def SecBufferDesc.create(token)
|
137
|
+
desc = API::SecBufferDesc.malloc
|
138
|
+
desc.version = 0
|
139
|
+
desc.count = 1
|
140
|
+
desc.buffers = SecBuffer.createArray([SECBUFFER_TOKEN], [token]).first.to_ptr
|
141
|
+
desc
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def self.max_token; @@max_token end
|
146
|
+
|
147
|
+
# SSPI - Kerberos 5 mechanism support.
|
148
|
+
result = API.querySecurityPackageInfo "Kerberos", nil
|
149
|
+
if result.ok? and ! (pkg_info = API._args_[1]).nil?
|
150
|
+
@@max_token = pkg_info.max_token
|
151
|
+
API.freeContextBuffer pkg_info
|
152
|
+
else
|
153
|
+
raise "SSPI reports no support for Kerberos authentication"
|
154
|
+
end
|
155
|
+
|
156
|
+
class Context < Net::SSH::Kerberos::Context
|
157
|
+
def init(token=nil)
|
158
|
+
prev = @state.handle if @state && ! @state.handle.nil?
|
159
|
+
ctx = prev || API::SecHandle.malloc
|
160
|
+
input = API::SecBufferDesc.create(token) if token
|
161
|
+
output = API::SecBufferDesc.create(12288)
|
162
|
+
result = API.initializeSecurityContext @credentials, prev, @target,
|
163
|
+
ISC_REQ_DELEGATE | ISC_REQ_MUTUAL_AUTH | ISC_REQ_INTEGRITY, 0,
|
164
|
+
SECURITY_NATIVE_DREP, input, 0, ctx, output, 0, ts=API::TimeStamp.malloc
|
165
|
+
result.failure? and raise GeneralError, "Error initializing security context: #{result}"
|
166
|
+
result = API.completeAuthToken ctx, output if result.incomplete?
|
167
|
+
result.failure? and raise GeneralError, "Error initializing security context: #{result}"
|
168
|
+
@state = State.new(ctx, result, output.buffers ? output.buffer(0).to_s : nil, ts)
|
169
|
+
if result.complete?
|
170
|
+
result = API.queryContextAttributes @state.handle, SECPKG_ATTR_SIZES, @sizes=API::SecPkgSizes.malloc
|
171
|
+
result.failure? and raise GeneralError, "Error initializing security context: #{result}"
|
172
|
+
@handle = @state.handle
|
173
|
+
end
|
174
|
+
@state.token
|
175
|
+
end
|
176
|
+
|
177
|
+
def get_mic(token)
|
178
|
+
desc = API::SecBufferDesc.malloc
|
179
|
+
desc.version = 0
|
180
|
+
desc.count = 2
|
181
|
+
desc.buffers = API::SecBuffer.createArray([SECBUFFER_DATA, SECBUFFER_TOKEN],
|
182
|
+
[token, @sizes.max_signature]).first.to_ptr
|
183
|
+
@state.result = API.makeSignature @handle, 0, desc, 0
|
184
|
+
@state.result.complete? or raise GeneralError, "Error creating the signature: #{result}"
|
185
|
+
desc.buffer(1).to_s
|
186
|
+
end
|
187
|
+
|
188
|
+
private
|
189
|
+
|
190
|
+
def acquire_current_credentials
|
191
|
+
result = API.acquireCredentialsHandle nil, "Kerberos", SECPKG_CRED_OUTBOUND, nil, nil, nil, nil,
|
192
|
+
creds=API::SecHandle.malloc, ts=API::TimeStamp.malloc
|
193
|
+
result.ok? or raise GeneralError, "Error acquiring credentials: #{result}"
|
194
|
+
result = API.queryCredentialsAttributes creds, SECPKG_ATTR_NAMES, nil
|
195
|
+
if result.ok?
|
196
|
+
name = API._args_[2]
|
197
|
+
begin return [creds, name.to_s]
|
198
|
+
ensure API.freeContextBuffer name
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
def release_credentials(creds) API.freeCredentialsHandle creds unless creds.nil? end
|
204
|
+
|
205
|
+
def import_server_name(host) ['host/'+host, 'host/'+host] end
|
206
|
+
|
207
|
+
def release_server_name(target) end
|
208
|
+
|
209
|
+
def delete_context(handle)
|
210
|
+
API.deleteSecurityContext handle unless handle.nil?
|
211
|
+
API.freeContextBuffer @sizes unless @sizes.nil?
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
end; end; end; end
|
data/test/gss_context_test.rb
CHANGED
@@ -2,10 +2,10 @@ require File.join(File.dirname(__FILE__), 'test_helper.rb')
|
|
2
2
|
|
3
3
|
class GssContextTest < Test::Unit::TestCase
|
4
4
|
|
5
|
-
if
|
5
|
+
if Net::SSH::Kerberos::Drivers.available.include? 'GSS'
|
6
6
|
|
7
7
|
def setup
|
8
|
-
@gss = Net::SSH::Kerberos::GSS::Context.new
|
8
|
+
@gss = Net::SSH::Kerberos::Drivers::GSS::Context.new
|
9
9
|
end
|
10
10
|
|
11
11
|
def teardown
|
@@ -22,13 +22,12 @@ if defined? Net::SSH::Kerberos::GSS::Context
|
|
22
22
|
@gss.init nil
|
23
23
|
state = @gss.send(:state)
|
24
24
|
assert ! state.handle.nil?, "Should have provided an initial context"
|
25
|
-
assert ! state.handle.handle.nil?, "Should have provided an initial context"
|
26
25
|
assert ! state.token.nil?, "Should have built an initial token"
|
27
26
|
assert state.token.length.nonzero?, "Should have built an initial token"
|
28
27
|
end
|
29
28
|
|
30
29
|
else
|
31
|
-
|
30
|
+
def test_nothing; assert true end
|
32
31
|
end
|
33
32
|
|
34
33
|
end
|
data/test/gss_test.rb
CHANGED
@@ -2,42 +2,38 @@ require File.join(File.dirname(__FILE__), 'test_helper.rb')
|
|
2
2
|
|
3
3
|
class GssTest < Test::Unit::TestCase
|
4
4
|
|
5
|
-
|
5
|
+
if Net::SSH::Kerberos::Drivers.available.include? 'GSS'
|
6
|
+
|
7
|
+
include Net::SSH::Kerberos::Drivers::GSS
|
6
8
|
|
7
9
|
def test_acquire_cred
|
8
|
-
|
9
|
-
result
|
10
|
-
|
10
|
+
result = API.gss_acquire_cred nil, 60, nil, GSS_C_INITIATE, nil, nil, 0
|
11
|
+
assert result.ok?, "gss_acquire_cred failed: #{result}"
|
12
|
+
creds = API._args_[4]
|
13
|
+
assert_not_equal creds, GSS_C_NO_CREDENTIAL, "Should acquire default credentials"
|
11
14
|
begin
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
assert_not_equal 0, oids.oidset.count, "Should provide the supported oids"
|
15
|
+
result = API.gss_inquire_cred creds, nil, 0, 0, nil
|
16
|
+
assert result.ok?, "gss_inquire_cred failed: #{result}"
|
17
|
+
name, oids = API._args_[1], API._args_[4]
|
18
|
+
assert_not_equal name, GSS_C_NO_NAME, "Should provide the internal name"
|
19
|
+
assert_not_equal oids, GSS_C_NO_OID_SET, "Should provide the supported oids"
|
20
|
+
assert oids.count > 0, "Should provide the supported oids"
|
19
21
|
begin
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
result = call_and_assert :gss_display_name, name.handle, buffer, oid
|
24
|
-
assert_not_equal 0, buffer.value.to_i, "Should provide the display name"
|
22
|
+
result = API.gss_display_name name, buffer=API::GssBuffer.malloc, nil
|
23
|
+
assert result.ok?, "gss_display_name failed: #{result}"
|
24
|
+
assert buffer.length > 0, "Should provide the display name"
|
25
25
|
begin
|
26
|
-
assert_not_equal
|
26
|
+
assert_not_equal API._args_[2], GSS_C_NO_OID, "Should provide the supported oid"
|
27
27
|
#$stderr.puts "credentials: #{creds.handle.to_i} #{buffer.value} (OID: #{oid.oid.length}, #{oid.oid.to_hex})"
|
28
28
|
ensure
|
29
|
-
|
29
|
+
API.gss_release_buffer buffer
|
30
30
|
end
|
31
31
|
ensure
|
32
|
-
|
33
|
-
API.
|
34
|
-
API.gss_release_oid_set minor_status, oids
|
35
|
-
assert_equal 0, name.handle.to_i, "Should release the internal name"
|
36
|
-
assert_equal 0, oids.ptr.to_i, "Should release the supported oids"
|
32
|
+
API.gss_release_name name
|
33
|
+
API.gss_release_oid_set oids
|
37
34
|
end
|
38
35
|
ensure
|
39
|
-
|
40
|
-
API.gss_release_cred minor_status, creds
|
36
|
+
API.gss_release_cred creds
|
41
37
|
end
|
42
38
|
end
|
43
39
|
|
@@ -46,52 +42,38 @@ class GssTest < Test::Unit::TestCase
|
|
46
42
|
buffer = API::GssBuffer.malloc
|
47
43
|
buffer.value = target_name
|
48
44
|
buffer.length = target_name.length
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
result =
|
54
|
-
|
55
|
-
|
56
|
-
buffer = API::GssBuffer.malloc
|
57
|
-
result = call_and_assert :gss_display_name, target_name.handle, buffer, nil
|
58
|
-
assert_not_equal 0, buffer.value.to_i, "Should provide the display name"
|
45
|
+
result = API.gss_import_name buffer, GSS_C_NT_HOSTBASED_SERVICE, nil
|
46
|
+
assert result.ok?, "gss_import_name failed: #{result}"
|
47
|
+
target = API._args_[2]
|
48
|
+
assert_not_equal target, GSS_C_NO_NAME, "Should import the name"
|
49
|
+
result = API.gss_display_name target, buffer=API::GssBuffer.malloc, nil
|
50
|
+
assert result.ok?, "gss_display_name failed: #{result}"
|
51
|
+
assert buffer.length > 0, "Should provide the display name"
|
59
52
|
#$stderr.puts "target: #{buffer.value} (OID: #{mech.length}, #{mech.to_hex})"
|
60
|
-
|
53
|
+
API.gss_release_buffer buffer
|
61
54
|
|
62
|
-
mech.elements = GSS_KRB5_MECH
|
63
|
-
mech.length = GSS_KRB5_MECH.length
|
64
|
-
actual_mech = API::GssOIDRef.malloc
|
65
|
-
context = API::GssContextRef.malloc
|
66
|
-
context.handle = GSS_C_NO_CONTEXT
|
67
55
|
buffer.value = nil
|
68
56
|
buffer.length = 0
|
69
|
-
result =
|
70
|
-
|
71
|
-
|
72
|
-
|
57
|
+
result = API.gss_init_sec_context GSS_C_NO_CREDENTIAL, GSS_C_NO_CONTEXT, target, GSS_C_KRB5,
|
58
|
+
GSS_C_DELEG_FLAG | GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG, 60,
|
59
|
+
GSS_C_NO_CHANNEL_BINDINGS, GSS_C_NO_BUFFER, nil, buffer, 0, 0
|
60
|
+
assert result.ok?, "gss_init_sec_context failed: #{result}"
|
61
|
+
context, actual_mech = API._args_[1], API._args_[8]
|
62
|
+
assert_not_equal context, GSS_C_NO_CONTEXT, "Should initialize the security context"
|
73
63
|
begin
|
74
|
-
assert_equal
|
64
|
+
assert_equal result.status, GSS_S_CONTINUE_NEEDED, "Should need continued initialization of the security context"
|
75
65
|
assert buffer.length > 0, "Should output a token to send to the server"
|
66
|
+
assert_not_equal actual_mech, GSS_C_NO_OID, "Should initialize the security context"
|
76
67
|
#$stderr.puts "context: (#{buffer.length}) (OID: #{actual_mech.oid.length}, #{actual_mech.oid.to_hex})"
|
77
|
-
|
68
|
+
API.gss_release_buffer buffer
|
78
69
|
ensure
|
79
|
-
|
80
|
-
API.gss_delete_sec_context minor_status, context, nil
|
81
|
-
if buffer.value.nil?
|
82
|
-
assert_equal 0, context.handle.to_i, "Should delete the security context"
|
83
|
-
end
|
70
|
+
API.gss_delete_sec_context context, nil if context and buffer.value.nil?
|
84
71
|
end
|
85
72
|
end
|
86
73
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
result = API.send sym, minor_status, *args
|
92
|
-
assert_equal 0, (result & 0xffff0000), "#{sym} failed: 0x#{result.to_s(16)}"
|
93
|
-
assert_equal 0, minor_status.value, "#{sym} failed: minor status 0x#{minor_status.value.to_s(16)}"
|
94
|
-
result
|
95
|
-
end
|
74
|
+
else
|
75
|
+
def test_nothing; assert true end
|
76
|
+
end
|
77
|
+
|
96
78
|
end
|
97
79
|
|
data/test/sspi_context_test.rb
CHANGED
@@ -2,10 +2,10 @@ require File.join(File.dirname(__FILE__), 'test_helper.rb')
|
|
2
2
|
|
3
3
|
class SspiContextTest < Test::Unit::TestCase
|
4
4
|
|
5
|
-
if
|
5
|
+
if Net::SSH::Kerberos::Drivers.available.include? 'SSPI'
|
6
6
|
|
7
7
|
def setup
|
8
|
-
@gss = Net::SSH::Kerberos::SSPI::Context.new
|
8
|
+
@gss = Net::SSH::Kerberos::Drivers::SSPI::Context.new
|
9
9
|
end
|
10
10
|
|
11
11
|
def teardown
|
@@ -18,8 +18,6 @@ if defined? Net::SSH::Kerberos::SSPI::Context
|
|
18
18
|
end
|
19
19
|
|
20
20
|
else
|
21
|
-
$stderr.puts "Skipping SSPI tests on this platform: Windows SSPI was not loaded."
|
22
|
-
|
23
21
|
def test_nothing; assert true end
|
24
22
|
end
|
25
23
|
|
data/test/sspi_test.rb
CHANGED
@@ -2,69 +2,61 @@ require File.join(File.dirname(__FILE__), 'test_helper.rb')
|
|
2
2
|
|
3
3
|
class SspiTest < Test::Unit::TestCase
|
4
4
|
|
5
|
-
if
|
5
|
+
if Net::SSH::Kerberos::Drivers.available.include? 'SSPI'
|
6
6
|
|
7
|
-
include
|
7
|
+
include Net::SSH::Kerberos::Drivers::SSPI
|
8
8
|
|
9
9
|
def test_query_security_package_info
|
10
|
-
|
11
|
-
result
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
assert pkg_info.max_token
|
16
|
-
|
17
|
-
|
10
|
+
result = API.querySecurityPackageInfo "Kerberos", nil
|
11
|
+
assert result.ok?, "querySecurityPackageInfo failed: #{result}"
|
12
|
+
#$stderr.puts "querySecurityPackageInfo => #{pkg_info.comment} (max_token=#{pkg_info.max_token})"
|
13
|
+
pkg_info = API._args_[1]
|
14
|
+
assert_equal pkg_info.name.to_s, "Kerberos"
|
15
|
+
assert pkg_info.max_token >= 128, "The maximum token size is assumed to be greater than 127 bytes"
|
16
|
+
assert pkg_info.max_token <= 12288, "The maximum token size is assumed to be less than 12289 bytes"
|
17
|
+
result = API.freeContextBuffer pkg_info
|
18
|
+
assert result.ok?, "freeContextBuffer failed: #{result}"
|
18
19
|
end
|
19
20
|
|
20
21
|
def test_security_context_initialization
|
21
|
-
|
22
|
-
|
23
|
-
result = API::AcquireCredentialsHandle nil, "Kerberos", SECPKG_CRED_OUTBOUND, nil, nil, nil, nil, creds, ts
|
22
|
+
result = API.acquireCredentialsHandle nil, "Kerberos", SECPKG_CRED_OUTBOUND, nil, nil, nil, nil,
|
23
|
+
creds=API::SecHandle.malloc, ts=API::TimeStamp.malloc
|
24
24
|
unless result.temporary_failure?
|
25
|
-
assert result.ok?, "
|
25
|
+
assert result.ok?, "acquireCredentialsHandle failed: #{result}"
|
26
26
|
assert ! creds.nil?, "Should acquire a credentials handle"
|
27
27
|
begin
|
28
|
-
|
29
|
-
result
|
30
|
-
|
31
|
-
names = buff.to_ptr.ptr
|
28
|
+
result = API.queryCredentialsAttributes creds, SECPKG_ATTR_NAMES, nil
|
29
|
+
assert result.ok?, "queryCredentialsAttributes failed: #{result}"
|
30
|
+
names = API._args_[2]
|
32
31
|
assert ! names.nil?, "Should return the user name."
|
32
|
+
#$stderr.puts "queryCredentialsAttributes: (#{result}) #{names.to_s}"
|
33
33
|
begin
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
req = ISC_REQ_DELEGATE | ISC_REQ_MUTUAL_AUTH
|
39
|
-
result = API::InitializeSecurityContext creds, nil, 'host/'+Socket.gethostbyname('localhost')[0],
|
40
|
-
req, 0, SECURITY_NATIVE_DREP, nil, 0, ctx, output, ctxAttr, ts
|
34
|
+
output = API::SecBufferDesc.create(12288)
|
35
|
+
result = API.initializeSecurityContext creds, nil, 'host/'+Socket.gethostbyname('localhost')[0],
|
36
|
+
ISC_REQ_DELEGATE | ISC_REQ_MUTUAL_AUTH | ISC_REQ_INTEGRITY, 0, SECURITY_NATIVE_DREP,
|
37
|
+
nil, 0, ctx=API::SecHandle.malloc, output, 0, ts=API::TimeStamp.malloc
|
41
38
|
unless result.temporary_failure?
|
42
|
-
assert result.ok?, "
|
39
|
+
assert result.ok?, "initializeSecurityContext failed: #{result}"
|
43
40
|
begin
|
44
41
|
assert ! ctx.nil?, "Should initialize a context handle"
|
45
|
-
assert ! output.
|
46
|
-
assert output.
|
42
|
+
assert ! output.buffer(0).data.nil?, "Should output a token into the buffer"
|
43
|
+
assert output.buffer(0).length < 12288, "Should output a token into the buffer"
|
47
44
|
ensure
|
48
|
-
result = API
|
49
|
-
ctx = nil if result.ok?
|
45
|
+
ctx = nil if (result = API.deleteSecurityContext(ctx)).ok?
|
50
46
|
end
|
51
|
-
assert ctx.nil?, "
|
47
|
+
assert ctx.nil?, "deleteSecurityContext failed: #{result}"
|
52
48
|
end
|
53
49
|
ensure
|
54
|
-
result = API
|
55
|
-
names = nil if result.ok?
|
50
|
+
names = nil if (result = API.freeContextBuffer(names)).ok?
|
56
51
|
end
|
57
|
-
assert names.nil?, "
|
52
|
+
assert names.nil?, "freeContextBuffer failed: #{result}"
|
58
53
|
ensure
|
59
|
-
result = API
|
60
|
-
creds = nil if result.ok?
|
54
|
+
creds = nil if (result = API.freeCredentialsHandle(creds)).ok?
|
61
55
|
end
|
62
|
-
assert creds.nil?, "
|
56
|
+
assert creds.nil?, "freeCredentialsHandle failed: #{result}"
|
63
57
|
end
|
64
58
|
end
|
65
59
|
else
|
66
|
-
$stderr.puts "Skipping SSPI tests on this platform: Windows SSPI was not loaded."
|
67
|
-
|
68
60
|
def test_nothing; assert true end
|
69
61
|
end
|
70
62
|
|