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