net-ssh-kerberos 0.1.3 → 0.2.0
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.
- 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
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: net-ssh-kerberos
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joe Khoobyar
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-10-
|
12
|
+
date: 2009-10-18 00:00:00 -04:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -22,18 +22,8 @@ dependencies:
|
|
22
22
|
- !ruby/object:Gem::Version
|
23
23
|
version: "2.0"
|
24
24
|
version:
|
25
|
-
- !ruby/object:Gem::Dependency
|
26
|
-
name: rubysspi
|
27
|
-
type: :runtime
|
28
|
-
version_requirement:
|
29
|
-
version_requirements: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - ">="
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: "1.3"
|
34
|
-
version:
|
35
25
|
description: |
|
36
|
-
|
26
|
+
Extends Net::SSH by adding Kerberos authentication capability for password-less logins on multiple platforms.
|
37
27
|
|
38
28
|
email: joe@ankhcraft.com
|
39
29
|
executables: []
|
@@ -50,17 +40,14 @@ files:
|
|
50
40
|
- VERSION.yml
|
51
41
|
- lib/net/ssh/authentication/methods/gssapi_with_mic.rb
|
52
42
|
- lib/net/ssh/kerberos.rb
|
53
|
-
- lib/net/ssh/kerberos/common/context.rb
|
54
43
|
- lib/net/ssh/kerberos/constants.rb
|
55
|
-
- lib/net/ssh/kerberos/
|
56
|
-
- lib/net/ssh/kerberos/
|
57
|
-
- lib/net/ssh/kerberos/gss
|
44
|
+
- lib/net/ssh/kerberos/context.rb
|
45
|
+
- lib/net/ssh/kerberos/drivers.rb
|
46
|
+
- lib/net/ssh/kerberos/drivers/gss.rb
|
47
|
+
- lib/net/ssh/kerberos/drivers/sspi.rb
|
58
48
|
- lib/net/ssh/kerberos/kex.rb
|
59
49
|
- lib/net/ssh/kerberos/kex/krb5_diffie_hellman_group1_sha1.rb
|
60
50
|
- lib/net/ssh/kerberos/kex/krb5_diffie_hellman_group_exchange_sha1.rb
|
61
|
-
- lib/net/ssh/kerberos/sspi.rb
|
62
|
-
- lib/net/ssh/kerberos/sspi/api.rb
|
63
|
-
- lib/net/ssh/kerberos/sspi/context.rb
|
64
51
|
- test/gss_context_test.rb
|
65
52
|
- test/gss_test.rb
|
66
53
|
- test/net_ssh_kerberos_test.rb
|
@@ -1,71 +0,0 @@
|
|
1
|
-
module Net; module SSH; module Kerberos; module Common; class Context
|
2
|
-
|
3
|
-
class GeneralError < StandardError; end
|
4
|
-
|
5
|
-
class State < Struct.new(:handle, :result, :token, :timestamp)
|
6
|
-
def complete?; result.complete? end
|
7
|
-
end
|
8
|
-
|
9
|
-
attr_reader :cred_name, :cred_krb_name, :server_name, :server_krb_name
|
10
|
-
|
11
|
-
def initialize
|
12
|
-
raise "Don't create this class directly - use a subclass" if self.class == Context
|
13
|
-
end
|
14
|
-
|
15
|
-
def create(user, host)
|
16
|
-
dispose if @credentials or @target or @handle
|
17
|
-
|
18
|
-
creds, name = acquire_current_credentials
|
19
|
-
begin
|
20
|
-
@cred_name = name.to_s.sub(/^[^\\\/]*[\\\/]/, '')
|
21
|
-
@cred_krb_name = @cred_name.gsub('@', '/');
|
22
|
-
|
23
|
-
z = (user.include?('@') ? user.gsub('@','/') : user+'/')
|
24
|
-
unless z.downcase == @cred_krb_name[0,z.length].downcase
|
25
|
-
raise GeneralError, "Credentials mismatch: current is #{@cred_name}, requested is #{user}"
|
26
|
-
end
|
27
|
-
@credentials = creds
|
28
|
-
ensure
|
29
|
-
if @credentials.nil?
|
30
|
-
release_credentials creds
|
31
|
-
@cred_name = @cred_krb_name = nil
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
@server_name = Socket.gethostbyname(host)[0]
|
36
|
-
@target, @server_krb_name = import_server_name host
|
37
|
-
|
38
|
-
true
|
39
|
-
end
|
40
|
-
|
41
|
-
def credentials?; ! @credentials.nil? end
|
42
|
-
|
43
|
-
def established?; ! @handle.nil? && (@state.nil? || @state.complete?) end
|
44
|
-
|
45
|
-
def init(token=nil); raise NotImplementedError, "subclasses must implement this method" end
|
46
|
-
|
47
|
-
def get_mic(token=nil); raise NotImplementedError, "subclasses must implement this method" end
|
48
|
-
|
49
|
-
def dispose
|
50
|
-
@handle and delete_context @handle
|
51
|
-
@credentials and release_credentials @credentials
|
52
|
-
@target and release_server_name @target
|
53
|
-
ensure
|
54
|
-
@credentials = @cred_name = @cred_krb_name = nil
|
55
|
-
@target = @server_name = @server_krb_name = nil
|
56
|
-
@handle = @state = nil
|
57
|
-
end
|
58
|
-
|
59
|
-
private
|
60
|
-
|
61
|
-
def acquire_current_credentials; raise NotImplementedError, "subclasses must implement this method" end
|
62
|
-
|
63
|
-
def release_credentials(creds); raise NotImplementedError, "subclasses must implement this method" end
|
64
|
-
|
65
|
-
def import_server_name(host); raise NotImplementedError, "subclasses must implement this method" end
|
66
|
-
|
67
|
-
def release_server_name(target); raise NotImplementedError, "subclasses must implement this method" end
|
68
|
-
|
69
|
-
def delete_context(handle); raise NotImplementedError, "subclasses must implement this method" end
|
70
|
-
|
71
|
-
end; end; end; end; end
|
data/lib/net/ssh/kerberos/gss.rb
DELETED
@@ -1,9 +0,0 @@
|
|
1
|
-
if ! defined? Net::SSH::Kerberos::SSPI::Context
|
2
|
-
$stderr.puts "warning: Kerberos support using GSSAPI is not fully tested."
|
3
|
-
end
|
4
|
-
|
5
|
-
require 'net/ssh/kerberos/gss/api'
|
6
|
-
require 'net/ssh/kerberos/gss/context'
|
7
|
-
|
8
|
-
module Net; module SSH; module Kerberos; module GSS
|
9
|
-
end; end; end; end
|
@@ -1,163 +0,0 @@
|
|
1
|
-
require 'dl/import'
|
2
|
-
require 'dl/struct'
|
3
|
-
|
4
|
-
module Net; module SSH; module Kerberos; module GSS;
|
5
|
-
|
6
|
-
module API
|
7
|
-
|
8
|
-
extend DL::Importable
|
9
|
-
|
10
|
-
def self.struct2(fields, &block)
|
11
|
-
t = struct fields
|
12
|
-
return t unless block_given?
|
13
|
-
t.instance_variable_set :@methods, Module.new(&block)
|
14
|
-
class << t
|
15
|
-
alias :new_struct :new
|
16
|
-
def new(ptr)
|
17
|
-
mem = new_struct(ptr)
|
18
|
-
mem.extend @methods
|
19
|
-
mem
|
20
|
-
end
|
21
|
-
end
|
22
|
-
t
|
23
|
-
end
|
24
|
-
|
25
|
-
if RUBY_PLATFORM =~ /cygwin/
|
26
|
-
dlload('cyggss-1.dll')
|
27
|
-
else
|
28
|
-
dlload('libgssapi_krb5.so')
|
29
|
-
end
|
30
|
-
|
31
|
-
typealias 'OM_uint32', 'unsigned int'
|
32
|
-
typealias 'size_t', 'unsigned int'
|
33
|
-
|
34
|
-
GssBuffer = struct [ "size_t length", "char *value" ]
|
35
|
-
typealias 'gss_buffer_desc', 'GssBuffer'
|
36
|
-
typealias 'gss_buffer_t', 'gss_buffer_desc *'
|
37
|
-
GssOID = struct2 [ "OM_uint32 length", "char *elements" ] do
|
38
|
-
def to_hex
|
39
|
-
s = elements.to_s
|
40
|
-
s.unpack("H2" * s.length).join ' '
|
41
|
-
end
|
42
|
-
end
|
43
|
-
typealias 'gss_OID_desc', 'GssOID'
|
44
|
-
typealias 'gss_OID', 'gss_OID_desc *'
|
45
|
-
GssOIDSet = struct [ "size_t count", "gss_OID elements" ]
|
46
|
-
typealias 'gss_OID_set_desc', 'GssOIDSet'
|
47
|
-
typealias 'gss_OID_set', 'gss_OID_set_desc *'
|
48
|
-
|
49
|
-
typealias 'gss_ctx_id_t', 'void *'
|
50
|
-
typealias 'gss_cred_id_t', 'void *'
|
51
|
-
typealias 'gss_name_t', 'void *'
|
52
|
-
typealias 'gss_qop_t', 'OM_uint32'
|
53
|
-
typealias 'gss_cred_usage_t', 'int'
|
54
|
-
|
55
|
-
GssNameRef = struct [ "gss_name_t handle" ]
|
56
|
-
GssContextRef = struct [ "gss_ctx_id_t handle" ]
|
57
|
-
GssCredRef = struct [ "gss_cred_id_t handle" ]
|
58
|
-
OM_uint32Ref = struct [ "OM_uint32 value" ]
|
59
|
-
GssCredUsageRef = struct [ "int value" ]
|
60
|
-
|
61
|
-
GssOIDRef = struct2 [ "GssOID *ptr" ] do
|
62
|
-
def oid
|
63
|
-
@oid = GssOID.new(ptr) if (@oid.nil? or @oid.to_ptr != ptr) and ! ptr.nil?
|
64
|
-
@oid
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
GssOIDSetRef = struct2 [ "GssOIDSet *ptr" ] do
|
69
|
-
def oidset
|
70
|
-
@oidset = GssOIDSet.new(ptr) if (@oidset.nil? or @oidset.to_ptr != ptr) and ! ptr.nil?
|
71
|
-
@oidset
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
class GssResult < Struct.new(:major, :minor, :status, :calling_error, :routine_error)
|
76
|
-
def initialize(result, minor=nil)
|
77
|
-
self.major = (result >> 16) & 0x0000ffff
|
78
|
-
self.minor = minor.value if minor.respond_to? :value
|
79
|
-
self.status = result & 0x0000ffff
|
80
|
-
self.calling_error = (major >> 8) & 0x00ff
|
81
|
-
self.routine_error = major & 0x00ff
|
82
|
-
end
|
83
|
-
|
84
|
-
def ok?; major.zero? end
|
85
|
-
|
86
|
-
def complete?; status.zero? end
|
87
|
-
|
88
|
-
def incomplete?; false end
|
89
|
-
|
90
|
-
def failure?; major.nonzero? end
|
91
|
-
|
92
|
-
def temporary_failure?
|
93
|
-
routine_error==GSS_S_CREDENTIALS_EXPIRED ||
|
94
|
-
routine_error==GSS_S_CONTEXT_EXPIRED ||
|
95
|
-
routine_error==GSS_S_UNAVAILABLE
|
96
|
-
end
|
97
|
-
|
98
|
-
def to_s; "%#4.4x%4.4x [%#8.8x]" % [major, status, minor] end
|
99
|
-
end
|
100
|
-
|
101
|
-
extern "OM_uint32 gss_acquire_cred (OM_uint32 *, gss_name_t, OM_uint32, gss_OID_set, gss_cred_usage_t, gss_cred_id_t *, gss_OID_set *, OM_uint32 *)"
|
102
|
-
extern "OM_uint32 gss_inquire_cred (OM_uint32 *, gss_cred_id_t, gss_name_t *, OM_uint32 *, gss_cred_usage_t *, gss_OID_set *)"
|
103
|
-
extern "OM_uint32 gss_release_cred (OM_uint32 *, gss_cred_id_t *)"
|
104
|
-
extern "OM_uint32 gss_import_name (OM_uint32 *, gss_buffer_t, gss_OID, gss_name_t *)"
|
105
|
-
extern "OM_uint32 gss_release_name (OM_uint32 *, gss_name_t *)"
|
106
|
-
extern "OM_uint32 gss_display_name (OM_uint32 *, gss_name_t, gss_buffer_t, gss_OID *)"
|
107
|
-
extern "OM_uint32 gss_release_buffer (OM_uint32 *, gss_buffer_t)"
|
108
|
-
extern "OM_uint32 gss_release_oid_set (OM_uint32 *, gss_OID_set *)"
|
109
|
-
extern "OM_uint32 gss_init_sec_context (OM_uint32 *, gss_cred_id_t, gss_ctx_id_t *, gss_name_t, gss_OID, OM_uint32, OM_uint32, void *, gss_buffer_t, gss_OID *, gss_buffer_t, OM_uint32 *, OM_uint32 *)"
|
110
|
-
extern "OM_uint32 gss_delete_sec_context (OM_uint32 *, gss_ctx_id_t *, gss_buffer_t)"
|
111
|
-
extern "OM_uint32 gss_get_mic(OM_uint32 *, gss_ctx_id_t, gss_qop_t, gss_buffer_t, gss_buffer_t)"
|
112
|
-
|
113
|
-
if @LIBS.empty? and ! defined? Net::SSH::Kerberos::SSPI::Context
|
114
|
-
$stderr.puts "error: Failed to a find a supported GSS implementation on this platform (#{RUBY_PLATFORM})"
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
GSS_C_INITIATE = 1
|
119
|
-
|
120
|
-
GSS_C_DELEG_FLAG = 1
|
121
|
-
GSS_C_MUTUAL_FLAG = 2
|
122
|
-
GSS_C_REPLAY_FLAG = 4
|
123
|
-
GSS_C_SEQUENCE_FLAG = 8
|
124
|
-
GSS_C_CONF_FLAG = 16
|
125
|
-
GSS_C_INTEG_FLAG = 32
|
126
|
-
GSS_C_ANON_FLAG = 64
|
127
|
-
GSS_C_PROT_READY_FLAG = 128
|
128
|
-
GSS_C_TRANS_FLAG = 256
|
129
|
-
|
130
|
-
GSS_C_NO_NAME = nil
|
131
|
-
GSS_C_NO_BUFFER = nil
|
132
|
-
GSS_C_NO_OID = nil
|
133
|
-
GSS_C_NO_OID_SET = nil
|
134
|
-
GSS_C_NO_CONTEXT = nil
|
135
|
-
GSS_C_NO_CREDENTIAL = nil
|
136
|
-
GSS_C_NO_CHANNEL_BINDINGS = nil
|
137
|
-
GSS_C_QOP_DEFAULT = 0
|
138
|
-
|
139
|
-
GSS_S_COMPLETE = 0
|
140
|
-
GSS_S_CONTINUE_NEEDED = 1
|
141
|
-
GSS_S_DUPLICATE_TOKEN = 2
|
142
|
-
GSS_S_OLD_TOKEN = 4
|
143
|
-
GSS_S_UNSEQ_TOKEN = 8
|
144
|
-
GSS_S_GAP_TOKEN = 16
|
145
|
-
|
146
|
-
#--
|
147
|
-
# GSSAPI / Kerberos 5 OID(s)
|
148
|
-
#++
|
149
|
-
GSS_C_NT_PRINCIPAL = "\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x01"
|
150
|
-
GSS_C_NT_MACHINE_UID_NAME = "\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x02"
|
151
|
-
GSS_C_NT_STRING_UID_NAME = "\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x03"
|
152
|
-
GSS_C_NT_HOSTBASED_SERVICE = "\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x04"
|
153
|
-
GSS_C_NT_ANONYMOUS = "\x2b\x06\01\x05\x06\x03"
|
154
|
-
GSS_C_NT_EXPORT_NAME = "\x2b\x06\01\x05\x06\x04"
|
155
|
-
GSS_KRB5_MECH = "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"
|
156
|
-
GSS_KRB5_MECH_USER2USER = "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x03"
|
157
|
-
|
158
|
-
#--
|
159
|
-
# GSSAPI / Kerberos 5 Deprecated / Proprietary OID(s)
|
160
|
-
#++
|
161
|
-
GSS_C_NT_HOSTBASED_SERVICE_X = "\x2b\x06\x01\x05\x06\x02"
|
162
|
-
|
163
|
-
end; end; end; end
|
@@ -1,115 +0,0 @@
|
|
1
|
-
require 'net/ssh/kerberos/common/context'
|
2
|
-
require 'net/ssh/kerberos/gss/api'
|
3
|
-
|
4
|
-
module Net; module SSH; module Kerberos; module GSS; class Context < Common::Context
|
5
|
-
|
6
|
-
GssResult = API::GssResult
|
7
|
-
|
8
|
-
def init(token=nil)
|
9
|
-
minor_status = API::OM_uint32Ref.malloc
|
10
|
-
|
11
|
-
mech = API::GssOID.malloc
|
12
|
-
mech.elements = GSS_KRB5_MECH
|
13
|
-
mech.length = GSS_KRB5_MECH.length
|
14
|
-
actual_mech = API::GssOIDRef.malloc
|
15
|
-
buffer = API::GssBuffer.malloc
|
16
|
-
if token.nil?
|
17
|
-
input = GSS_C_NO_BUFFER
|
18
|
-
else
|
19
|
-
input = API::GssBuffer.malloc
|
20
|
-
input.value = token.to_ptr
|
21
|
-
input.length = token.length
|
22
|
-
end
|
23
|
-
if @state.nil? or @state.handle.nil?
|
24
|
-
context = API::GssContextRef.malloc
|
25
|
-
context.handle = GSS_C_NO_CONTEXT
|
26
|
-
else
|
27
|
-
context = @state.handle
|
28
|
-
end
|
29
|
-
result = GssResult.new API.gss_init_sec_context(minor_status, @credentials, context, @target.handle, mech,
|
30
|
-
GSS_C_DELEG_FLAG | GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG, 60,
|
31
|
-
GSS_C_NO_CHANNEL_BINDINGS, input, actual_mech, buffer, nil, nil), minor_status
|
32
|
-
result.failure? and raise GeneralError, "Error initializing security context: #{result.major} #{input.length}"
|
33
|
-
begin
|
34
|
-
@state = State.new(context, result, (buffer.value && buffer.value.to_s(buffer.length).dup), nil)
|
35
|
-
@handle = @state.handle if result.complete?
|
36
|
-
return @state.token
|
37
|
-
ensure
|
38
|
-
API.gss_release_buffer(minor_status, buffer) unless buffer.value.nil?
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
def get_mic(token=nil)
|
43
|
-
minor_status = API::OM_uint32Ref.malloc
|
44
|
-
input = API::GssBuffer.malloc
|
45
|
-
input.value = token.to_ptr
|
46
|
-
input.length = token.length
|
47
|
-
output = API::GssBuffer.malloc
|
48
|
-
@state.result = GssResult.new API.gss_get_mic(minor_status, @handle.handle, GSS_C_QOP_DEFAULT, input, output), minor_status
|
49
|
-
unless @state.result.complete? and output
|
50
|
-
raise GeneralError, "Error creating the signature: #{@state.result}"
|
51
|
-
end
|
52
|
-
begin return output.value.to_s(output.length).dup
|
53
|
-
ensure API.gss_release_buffer minor_status, output
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
protected
|
58
|
-
|
59
|
-
def state; @state end
|
60
|
-
|
61
|
-
private
|
62
|
-
|
63
|
-
def acquire_current_credentials
|
64
|
-
minor_status = API::OM_uint32Ref.malloc
|
65
|
-
creds = API::GssCredRef.malloc
|
66
|
-
result = GssResult.new API.gss_acquire_cred(minor_status, nil, 60, nil, GSS_C_INITIATE, creds, nil, nil), minor_status
|
67
|
-
result.ok? or raise GeneralError, "Error acquiring credentials: #{result}"
|
68
|
-
begin
|
69
|
-
name = API::GssNameRef.malloc
|
70
|
-
result = GssResult.new API.gss_inquire_cred(minor_status, creds.handle, name, nil, nil, nil), minor_status
|
71
|
-
result.ok? or raise GeneralError, "Error inquiring credentials: #{result}"
|
72
|
-
begin
|
73
|
-
buffer = API::GssBuffer.malloc
|
74
|
-
result = GssResult.new API.gss_display_name(minor_status, name.handle, buffer, nil), minor_status
|
75
|
-
result.ok? or raise GeneralError, "Error getting display name: #{result}"
|
76
|
-
begin return [creds, buffer.value.to_s.dup]
|
77
|
-
ensure API.gss_release_buffer API::OM_uint32Ref.malloc, buffer
|
78
|
-
end
|
79
|
-
ensure
|
80
|
-
API.gss_release_name API::OM_uint32Ref.malloc, name
|
81
|
-
end
|
82
|
-
ensure
|
83
|
-
API.gss_release_cred API::OM_uint32Ref.malloc, creds
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
def release_credentials(creds)
|
88
|
-
creds.nil? or API.gss_release_cred API::OM_uint32Ref.malloc, creds
|
89
|
-
end
|
90
|
-
|
91
|
-
def import_server_name(host)
|
92
|
-
host = 'host@' + host
|
93
|
-
minor_status = API::OM_uint32Ref.malloc
|
94
|
-
buffer = API::GssBuffer.malloc
|
95
|
-
buffer.value = host.to_ptr
|
96
|
-
buffer.length = host.length
|
97
|
-
mech = API::GssOID.malloc
|
98
|
-
mech.elements = GSS_C_NT_HOSTBASED_SERVICE
|
99
|
-
mech.length = GSS_C_NT_HOSTBASED_SERVICE.length
|
100
|
-
target = API::GssNameRef.malloc
|
101
|
-
result = GssResult.new API.gss_import_name(minor_status, buffer, mech, target), minor_status
|
102
|
-
result.failure? and raise GeneralError, "Error importing name: #{result} #{input.inspect}"
|
103
|
-
|
104
|
-
[target, host]
|
105
|
-
end
|
106
|
-
|
107
|
-
def release_server_name(target)
|
108
|
-
target.nil? or API.gss_release_name API::OM_uint32Ref.malloc, target
|
109
|
-
end
|
110
|
-
|
111
|
-
def delete_context(handle)
|
112
|
-
handle.nil? or API.gss_delete_sec_context API::OM_uint32Ref.malloc, handle, nil
|
113
|
-
end
|
114
|
-
|
115
|
-
end; end; end; end; end
|
@@ -1,228 +0,0 @@
|
|
1
|
-
require 'win32/sspi'
|
2
|
-
require 'dl'
|
3
|
-
|
4
|
-
module Win32; module SSPI
|
5
|
-
|
6
|
-
SECPKG_CRED_ATTR_NAMES = 1
|
7
|
-
|
8
|
-
ISC_REQ_DELEGATE = 0x00000001
|
9
|
-
ISC_REQ_MUTUAL_AUTH = 0x00000002
|
10
|
-
ISC_REQ_INTEGRITY = 0x00010000
|
11
|
-
|
12
|
-
SECPKG_ATTR_AUTHORITY = 6
|
13
|
-
SECPKG_ATTR_CONNECTION_INFO = 90
|
14
|
-
SECPKG_ATTR_ISSUER_LIST = 80
|
15
|
-
SECPKG_ATTR_ISSUER_LIST_EX = 89
|
16
|
-
SECPKG_ATTR_KEY_INFO = 5
|
17
|
-
SECPKG_ATTR_LIFESPAN = 2
|
18
|
-
SECPKG_ATTR_LOCAL_CERT_CONTEXT = 84
|
19
|
-
SECPKG_ATTR_LOCAL_CRED = 82
|
20
|
-
SECPKG_ATTR_NAMES = 1
|
21
|
-
SECPKG_ATTR_PROTO_INFO = 7
|
22
|
-
SECPKG_ATTR_REMOTE_CERT_CONTEXT = 83
|
23
|
-
SECPKG_ATTR_REMOTE_CRED = 81
|
24
|
-
SECPKG_ATTR_SIZES = 0
|
25
|
-
SECPKG_ATTR_STREAM_SIZES = 4
|
26
|
-
|
27
|
-
# Buffer types
|
28
|
-
SECBUFFER_EMPTY = 0
|
29
|
-
SECBUFFER_DATA = 1
|
30
|
-
SECBUFFER_TOKEN = 2
|
31
|
-
SECBUFFER_PKG_PARAMS = 3
|
32
|
-
SECBUFFER_MISSING = 4
|
33
|
-
SECBUFFER_EXTRA = 5
|
34
|
-
SECBUFFER_STREAM_TRAILER = 6
|
35
|
-
SECBUFFER_STREAM_HEADER = 7
|
36
|
-
SECBUFFER_PADDING = 9
|
37
|
-
SECBUFFER_STREAM = 10
|
38
|
-
SECBUFFER_MECHLIST = 11
|
39
|
-
SECBUFFER_MECHLIST_SIGNATURE = 12
|
40
|
-
SECBUFFER_TARGET = 13
|
41
|
-
SECBUFFER_CHANNEL_BINDINGS = 14
|
42
|
-
SECBUFFER_CHANGE_PASS_RESPONSE = 15
|
43
|
-
SECBUFFER_TARGET_HOST = 16
|
44
|
-
SECBUFFER_READONLY = 0x80000000
|
45
|
-
SECBUFFER_READONLY_WITH_CHECKSUM = 0x10000000
|
46
|
-
SECBUFFER_ATTRMASK = 0xf0000000
|
47
|
-
|
48
|
-
# Good results
|
49
|
-
SEC_E_OK = 0x00000000
|
50
|
-
SEC_I_RENEGOTIATE = 590625;
|
51
|
-
SEC_I_COMPLETE_AND_CONTINUE = 590612;
|
52
|
-
SEC_I_COMPLETE_NEEDED = 590611;
|
53
|
-
SEC_I_CONTINUE_NEEDED = 590610;
|
54
|
-
SEC_I_INCOMPLETE_CREDENTIALS = 590624;
|
55
|
-
|
56
|
-
# These are generally returned by InitializeSecurityContext
|
57
|
-
SEC_E_INSUFFICIENT_MEMORY = 0x80090300
|
58
|
-
SEC_E_INTERNAL_ERROR = 0x80090304
|
59
|
-
SEC_E_INVALID_HANDLE = 0x80090301
|
60
|
-
SEC_E_INVALID_TOKEN = 0x80090308
|
61
|
-
SEC_E_LOGON_DENIED = 0x8009030C
|
62
|
-
SEC_E_NO_AUTHENTICATING_AUTHORITY = 0x80090311
|
63
|
-
SEC_E_NO_CREDENTIALS = 0x8009030E
|
64
|
-
SEC_E_TARGET_UNKNOWN = 0x80090303
|
65
|
-
SEC_E_UNSUPPORTED_FUNCTION = 0x80090302
|
66
|
-
SEC_E_WRONG_PRINCIPAL = 0x80090322
|
67
|
-
|
68
|
-
# These are generally returned by AcquireCredentialsHandle
|
69
|
-
SEC_E_NOT_OWNER = 0x80090306
|
70
|
-
SEC_E_SECPKG_NOT_FOUND = 0x80090305
|
71
|
-
SEC_E_UNKNOWN_CREDENTIALS = 0x8009030D
|
72
|
-
|
73
|
-
module API
|
74
|
-
QuerySecurityPackageInfo = Win32API.new("secur32", "QuerySecurityPackageInfoA", 'pp', 'L')
|
75
|
-
QueryCredentialsAttributes = Win32API.new("secur32", "QueryCredentialsAttributesA", 'pLp', 'L')
|
76
|
-
QueryContextAttributes = Win32API.new("secur32", "QueryContextAttributesA", 'pLp', 'L')
|
77
|
-
CompleteAuthToken = Win32API.new("secur32", "CompleteAuthToken", 'pp', 'L')
|
78
|
-
MakeSignature = Win32API.new("secur32", "MakeSignature", 'pLpL', 'L')
|
79
|
-
FreeContextBuffer = Win32API.new("secur32", "FreeContextBuffer", 'P', 'L')
|
80
|
-
|
81
|
-
private
|
82
|
-
|
83
|
-
def self.method_missing(symbol, *args)
|
84
|
-
return super unless const_defined? symbol and Win32API === (api = const_get(symbol))
|
85
|
-
result = SSPIResult.new api.call(*args)
|
86
|
-
args = (1..(args.length)).inject([]) { |v,n| v << "a#{n}" }.join ', '
|
87
|
-
class_eval "def self.#{symbol}(#{args}); SSPIResult.new #{symbol}.call(#{args}) end"
|
88
|
-
result
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
SecPkgCredentialsNames = Struct.new(:user_name)
|
93
|
-
|
94
|
-
class SecurityHandle
|
95
|
-
def nil?; @struct.unpack('Q').first.zero? end
|
96
|
-
alias :to_str :to_p
|
97
|
-
end
|
98
|
-
|
99
|
-
class TimeStamp
|
100
|
-
def nil?; @struct.unpack('Q').first.zero? end
|
101
|
-
alias :to_str :to_p
|
102
|
-
end
|
103
|
-
|
104
|
-
class SSPIResult
|
105
|
-
def ok?; (value & 0x80000000).zero? end
|
106
|
-
|
107
|
-
def complete?; value.zero? end
|
108
|
-
|
109
|
-
def incomplete?; SEC_I_COMPLETE_NEEDED==value || SEC_I_COMPLETE_AND_CONTINUE==value end
|
110
|
-
|
111
|
-
def failure?; (value & 0x80000000).nonzero? end
|
112
|
-
|
113
|
-
def temporary_failure?
|
114
|
-
value==SEC_E_LOGON_DENIED || value==SEC_E_NO_AUTHENTICATING_AUTHORITY || value==SEC_E_NO_CREDENTIALS
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
class SecPkgInfo
|
119
|
-
attr_reader :struct
|
120
|
-
|
121
|
-
def capabilities; unpacked[0] end
|
122
|
-
def max_token; unpacked[2] end
|
123
|
-
def name; unpacked[3] end
|
124
|
-
def comment; unpacked[4] end
|
125
|
-
|
126
|
-
def unpacked;
|
127
|
-
@unpacked ||= @struct.to_ptr.ptr.to_a("LLL", 3) + (@struct.to_ptr.ptr + 12).to_a("SS", 2)
|
128
|
-
end
|
129
|
-
|
130
|
-
def to_p; @struct ||= "\0" * 4 end
|
131
|
-
alias :to_str :to_p
|
132
|
-
end
|
133
|
-
|
134
|
-
class SecPkgSizes
|
135
|
-
attr_reader :struct
|
136
|
-
|
137
|
-
def max_token; unpacked[0] end
|
138
|
-
def max_signature; unpacked[1] end
|
139
|
-
def block_size; unpacked[2] end
|
140
|
-
def security_trailer; unpacked[3] end
|
141
|
-
|
142
|
-
def unpacked;
|
143
|
-
@unpacked ||= @struct.unpack("LLLL")
|
144
|
-
end
|
145
|
-
|
146
|
-
def to_p; @struct ||= "\0" * 16 end
|
147
|
-
alias :to_str :to_p
|
148
|
-
end
|
149
|
-
|
150
|
-
# Creates binary representaiton of a SecBufferDesc structure,
|
151
|
-
# including the SecBuffer contained inside.
|
152
|
-
class SecurityBuffer
|
153
|
-
|
154
|
-
def initialize(buffers=nil)
|
155
|
-
case buffers
|
156
|
-
when String
|
157
|
-
@bufferTokens = [ buffers.dup ]
|
158
|
-
@bufferSizes = [ buffers.length ]
|
159
|
-
@bufferTypes = [ SECBUFFER_TOKEN ]
|
160
|
-
when Fixnum
|
161
|
-
@bufferTokens = [ "\0" * TOKENBUFSIZE ] * buffers
|
162
|
-
@bufferSizes = [ TOKENBUFSIZE ] * buffers
|
163
|
-
@bufferTypes = [ SECBUFFER_TOKEN ] * buffers
|
164
|
-
when NilClass
|
165
|
-
@bufferTokens = [ "\0" * TOKENBUFSIZE ]
|
166
|
-
@bufferSizes = [ TOKENBUFSIZE ]
|
167
|
-
@bufferTypes = [ SECBUFFER_TOKEN ]
|
168
|
-
else
|
169
|
-
raise ArgumentError
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
|
-
def bufferSize(n=0)
|
174
|
-
unpack
|
175
|
-
@bufferSizes[n]
|
176
|
-
end
|
177
|
-
|
178
|
-
def bufferType(n=0)
|
179
|
-
unpack
|
180
|
-
@bufferTypes[n]
|
181
|
-
end
|
182
|
-
|
183
|
-
def token(n=0)
|
184
|
-
unpack
|
185
|
-
@bufferTokens[n]
|
186
|
-
end
|
187
|
-
|
188
|
-
def set_buffer(n=0, type=SECBUFFER_TOKEN, token=nil, size=nil)
|
189
|
-
@bufferTypes[n] = type
|
190
|
-
@bufferSizes[n] = size || (token.nil? ? 0 : token.length)
|
191
|
-
@bufferTokens[n] = (token.nil? && size && size > 0) ? "\0" * (size+1) : token
|
192
|
-
end
|
193
|
-
|
194
|
-
def to_p
|
195
|
-
# Assumption is that when to_p is called we are going to get a packed structure. Therefore,
|
196
|
-
# set @unpacked back to nil so we know to unpack when accessors are next accessed.
|
197
|
-
@unpacked = nil
|
198
|
-
# Assignment of inner structure to variable is very important here. Without it,
|
199
|
-
# will not be able to unpack changes to the structure. Alternative, nested unpacks,
|
200
|
-
# does not work (i.e. @struct.unpack("LLP12")[2].unpack("LLP12") results in "no associated pointer")
|
201
|
-
@sec_buffers ||= @bufferTokens.inject([]) do |v,t|
|
202
|
-
v.push @bufferSizes[v.size / 3], @bufferTypes[v.size / 3], t
|
203
|
-
end.pack("LLP" * @bufferTokens.size)
|
204
|
-
@struct ||= [SECBUFFER_VERSION, @bufferTokens.size, @sec_buffers].pack("LLP")
|
205
|
-
end
|
206
|
-
alias :to_str :to_p
|
207
|
-
|
208
|
-
private
|
209
|
-
|
210
|
-
# Unpacks the SecurityBufferDesc structure into member variables. We
|
211
|
-
# only want to do this once per struct, so the struct is deleted
|
212
|
-
# after unpacking.
|
213
|
-
def unpack
|
214
|
-
if ! @unpacked && @sec_buffers && @struct
|
215
|
-
d = @sec_buffers.unpack("LLL" * @bufferTokens.size)
|
216
|
-
k = ''; 0.upto(@bufferTokens.size - 1) do |n| k << "LLP#{d[n * 3]}" end
|
217
|
-
d = @sec_buffers.unpack(k)
|
218
|
-
0.upto(@bufferTokens.size - 1) do |n| @bufferSizes[n] = d[n * 3] end
|
219
|
-
0.upto(@bufferTokens.size - 1) do |n| @bufferTypes[n] = d[n * 3 + 1] end
|
220
|
-
0.upto(@bufferTokens.size - 1) do |n| @bufferTokens[n] = d[n * 3 + 2] end
|
221
|
-
@struct = nil
|
222
|
-
@sec_buffers = nil
|
223
|
-
@unpacked = true
|
224
|
-
end
|
225
|
-
end
|
226
|
-
end
|
227
|
-
|
228
|
-
end; end
|