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.
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.1.3
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-16 00:00:00 -04:00
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
- Adds support for Microsoft Kerberos (SSPI) with the Net:SSH gem.
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/gss.rb
56
- - lib/net/ssh/kerberos/gss/api.rb
57
- - lib/net/ssh/kerberos/gss/context.rb
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
@@ -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,5 +0,0 @@
1
- require 'net/ssh/kerberos/sspi/api'
2
- require 'net/ssh/kerberos/sspi/context'
3
-
4
- module Net; module SSH; module Kerberos; module SSPI
5
- 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