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
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
|