gssapi 1.0.1 → 1.0.2
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/VERSION +1 -1
- data/lib/gssapi.rb +1 -0
- data/lib/gssapi/exceptions.rb +35 -1
- data/lib/gssapi/lib_gssapi.rb +27 -29
- data/lib/gssapi/simple.rb +29 -22
- data/test/spec/gssapi_simple_spec.rb +24 -0
- data/test/spec/test_buffer_spec.rb +15 -0
- metadata +5 -5
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.0.
|
1
|
+
1.0.2
|
data/lib/gssapi.rb
CHANGED
data/lib/gssapi/exceptions.rb
CHANGED
@@ -4,5 +4,39 @@ Copyright © 2010 Dan Wanek <dan.wanek@gmail.com>
|
|
4
4
|
Licensed under the MIT License: http://www.opensource.org/licenses/mit-license.php
|
5
5
|
=end
|
6
6
|
module GSSAPI
|
7
|
-
class GssApiError < StandardError
|
7
|
+
class GssApiError < StandardError
|
8
|
+
|
9
|
+
include LibGSSAPI
|
10
|
+
|
11
|
+
def message; to_s + ": " + @s; end
|
12
|
+
|
13
|
+
def initialize(maj_stat = nil, min_stat = nil)
|
14
|
+
if(maj_stat.nil? && min_stat.nil?)
|
15
|
+
@s = '(no error info)'
|
16
|
+
else
|
17
|
+
min = FFI::MemoryPointer.new :OM_uint32
|
18
|
+
message_context = FFI::MemoryPointer.new :OM_uint32
|
19
|
+
@s = ''
|
20
|
+
oid = GssOID.gss_c_no_oid
|
21
|
+
min_stat = min_stat.read_uint32
|
22
|
+
[[maj_stat, GSS_C_GSS_CODE], [min_stat, GSS_C_MECH_CODE]].each do |m, t|
|
23
|
+
message_context.write_int 0
|
24
|
+
begin
|
25
|
+
out_buff = ManagedGssBufferDesc.new
|
26
|
+
maj = gss_display_status(min, m, t, oid, message_context, out_buff.pointer)
|
27
|
+
if (maj != 0)
|
28
|
+
@s += "failed to retrieve GSSAPI display for status #{m}"
|
29
|
+
@s += " of major status #{maj_stat}, minor_status #{min_stat}\n"
|
30
|
+
@s += "(with major status #{maj}, minor status #{min.read_uint32}\n"
|
31
|
+
break
|
32
|
+
end
|
33
|
+
@s += out_buff.value.to_s + "\n"
|
34
|
+
end while message_context.read_int != 0
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# We need to call this so we can pass the message to the Error when we have no arguments
|
39
|
+
super()
|
40
|
+
end
|
41
|
+
end
|
8
42
|
end
|
data/lib/gssapi/lib_gssapi.rb
CHANGED
@@ -10,12 +10,10 @@ module GSSAPI
|
|
10
10
|
# Libc functions
|
11
11
|
|
12
12
|
# void *malloc(size_t size);
|
13
|
-
attach_function :malloc, [:
|
13
|
+
attach_function :malloc, [:size_t], :pointer
|
14
14
|
|
15
15
|
# void *memcpy(void *dest, const void *src, size_t n);
|
16
|
-
attach_function :memcpy, [:pointer, :pointer, :
|
17
|
-
|
18
|
-
typedef :uint32, :OM_uint32
|
16
|
+
attach_function :memcpy, [:pointer, :pointer, :size_t], :pointer
|
19
17
|
|
20
18
|
class GssOID < FFI::Struct
|
21
19
|
layout :length => :OM_uint32,
|
@@ -58,8 +56,8 @@ module GSSAPI
|
|
58
56
|
module GssBufferDescLayout
|
59
57
|
def self.included(base)
|
60
58
|
base.class_eval do
|
61
|
-
layout :length => :
|
62
|
-
:value
|
59
|
+
layout :length => :OM_uint32,
|
60
|
+
:value => :pointer # pointer of :void
|
63
61
|
|
64
62
|
def length
|
65
63
|
self[:length]
|
@@ -108,7 +106,7 @@ module GSSAPI
|
|
108
106
|
elsif(val.is_a?(Fixnum))
|
109
107
|
buff = FFI::MemoryPointer.new :OM_uint32
|
110
108
|
buff.write_int val
|
111
|
-
self[:length] =
|
109
|
+
self[:length] = FFI::type_size :OM_uint32
|
112
110
|
self[:value] = buff
|
113
111
|
else
|
114
112
|
raise StandardError, "Can't handle type #{val.class.name}"
|
@@ -190,11 +188,7 @@ module GSSAPI
|
|
190
188
|
class GssCtxIdT < GssPointer
|
191
189
|
def self.release_ptr(context_ptr)
|
192
190
|
min_stat = FFI::MemoryPointer.new :OM_uint32
|
193
|
-
|
194
|
-
empty_buff = LibGSSAPI::UnManagedGssBufferDesc.new
|
195
|
-
empty_buff[:length] = 0
|
196
|
-
empty_buff[:value] = nil
|
197
|
-
maj_stat = LibGSSAPI.gss_delete_sec_context(min_stat, context_ptr, empty_buff.pointer)
|
191
|
+
maj_stat = LibGSSAPI.gss_delete_sec_context(min_stat, context_ptr, LibGSSAPI::GSS_C_NO_BUFFER)
|
198
192
|
end
|
199
193
|
|
200
194
|
def self.gss_c_no_context
|
@@ -335,6 +329,8 @@ module GSSAPI
|
|
335
329
|
# OM_uint32 krb5_gss_register_acceptor_identity(const char *);
|
336
330
|
attach_function :krb5_gss_register_acceptor_identity, [:string], :OM_uint32
|
337
331
|
|
332
|
+
# OM_uint32 gss_display_status(OM_uint32 *minor_status, OM_uint32 status_value, int status_type, gss_OID mech_type, OM_uint32 *message_context, gss_buffer_t status_string)
|
333
|
+
attach_function :gss_display_status, [:pointer, :OM_uint32, :int, :pointer, :pointer, :pointer], :OM_uint32
|
338
334
|
|
339
335
|
# Variable definitions
|
340
336
|
# --------------------
|
@@ -377,7 +373,9 @@ module GSSAPI
|
|
377
373
|
|
378
374
|
|
379
375
|
# GSSAPI Status & Error Codes
|
380
|
-
GSS_S_COMPLETE
|
376
|
+
GSS_S_COMPLETE = 0
|
377
|
+
GSS_C_GSS_CODE = 1
|
378
|
+
GSS_C_MECH_CODE = 2
|
381
379
|
|
382
380
|
GSS_C_CALLING_ERRORS = {
|
383
381
|
(1 << GSS_C_CALLING_ERROR_OFFSET) => "GSS_S_CALL_INACCESSIBLE_READ",
|
@@ -386,11 +384,11 @@ module GSSAPI
|
|
386
384
|
}
|
387
385
|
|
388
386
|
GSS_C_SUPPLEMENTARY_CODES = {
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
387
|
+
(1 << (GSS_C_SUPPLEMENTARY_OFFSET + 0)) => "GSS_S_CONTINUE_NEEDED",
|
388
|
+
(1 << (GSS_C_SUPPLEMENTARY_OFFSET + 1)) => "GSS_S_DUPLICATE_TOKEN",
|
389
|
+
(1 << (GSS_C_SUPPLEMENTARY_OFFSET + 2)) => "GSS_S_OLD_TOKEN",
|
390
|
+
(1 << (GSS_C_SUPPLEMENTARY_OFFSET + 3)) => "GSS_S_UNSEQ_TOKEN",
|
391
|
+
(1 << (GSS_C_SUPPLEMENTARY_OFFSET + 4)) => "GSS_S_GAP_TOKEN"
|
394
392
|
}
|
395
393
|
|
396
394
|
GSS_C_ROUTINE_ERRORS = {
|
@@ -417,10 +415,10 @@ module GSSAPI
|
|
417
415
|
|
418
416
|
# IOV Buffer Types (gssapi_ext.h)
|
419
417
|
GSS_IOV_BUFFER_TYPE_EMPTY = 0
|
420
|
-
GSS_IOV_BUFFER_TYPE_DATA = 1
|
421
|
-
GSS_IOV_BUFFER_TYPE_HEADER = 2
|
422
|
-
GSS_IOV_BUFFER_TYPE_MECH_PARAMS = 3
|
423
|
-
GSS_IOV_BUFFER_TYPE_TRAILER = 7
|
418
|
+
GSS_IOV_BUFFER_TYPE_DATA = 1 # Packet data
|
419
|
+
GSS_IOV_BUFFER_TYPE_HEADER = 2 # Mechanism header
|
420
|
+
GSS_IOV_BUFFER_TYPE_MECH_PARAMS = 3 # Mechanism specific parameters
|
421
|
+
GSS_IOV_BUFFER_TYPE_TRAILER = 7 # Mechanism trailer
|
424
422
|
GSS_IOV_BUFFER_TYPE_PADDING = 9 # Padding
|
425
423
|
GSS_IOV_BUFFER_TYPE_STREAM = 10 # Complete wrap token
|
426
424
|
GSS_IOV_BUFFER_TYPE_SIGN_ONLY = 11 # Sign only packet data
|
@@ -432,13 +430,13 @@ module GSSAPI
|
|
432
430
|
|
433
431
|
|
434
432
|
# Various Null values. (gssapi.h)
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
433
|
+
GSS_C_NO_NAME = FFI::Pointer.new(:pointer, 0) # ((gss_name_t) 0)
|
434
|
+
GSS_C_NO_BUFFER = FFI::Pointer.new(:pointer, 0) # ((gss_buffer_t) 0)
|
435
|
+
GSS_C_NO_OID = FFI::Pointer.new(:pointer, 0) # ((gss_OID) 0)
|
436
|
+
GSS_C_NO_OID_SET = FFI::Pointer.new(:pointer, 0) # ((gss_OID_set) 0)
|
437
|
+
GSS_C_NO_CONTEXT = FFI::Pointer.new(:pointer, 0) # ((gss_ctx_id_t) 0)
|
438
|
+
GSS_C_NO_CREDENTIAL = FFI::Pointer.new(:pointer, 0) # ((gss_cred_id_t) 0)
|
439
|
+
GSS_C_NO_CHANNEL_BINDINGS = FFI::Pointer.new(:pointer, 0) # ((gss_channel_bindings_t) 0)
|
442
440
|
GSS_C_EMPTY_BUFFER = ManagedGssBufferDesc.new
|
443
441
|
|
444
442
|
end #end LibGSSAPI
|
data/lib/gssapi/simple.rb
CHANGED
@@ -13,9 +13,12 @@ module GSSAPI
|
|
13
13
|
|
14
14
|
# Initialize a new GSSAPI::Simple object
|
15
15
|
# @param [String] host_name the fully qualified host name
|
16
|
-
# @param [String] service_name
|
17
|
-
#
|
18
|
-
#
|
16
|
+
# @param [String] service_name The service name. This can either be a
|
17
|
+
# GSS_KRB5_NT_PRINCIPAL_NAME in the form of srvc/fqdn@REALM
|
18
|
+
# or
|
19
|
+
# GSS_C_NT_HOSTBASED_SERVICE in the form of srvc@fqdn
|
20
|
+
# If there is no '@fqdn' part, the host_name will be appended.
|
21
|
+
# If no service_name is given at all the default service of 'host@fqdn' will be used.
|
19
22
|
def initialize(host_name, service_name=nil, keytab=nil)
|
20
23
|
@host = host_name
|
21
24
|
@service = service_name.nil? ? "host@#{@host}" : (service_name.include?('@') ? service_name : "#{service_name}@#{@host}")
|
@@ -31,13 +34,17 @@ module GSSAPI
|
|
31
34
|
def import_name(str)
|
32
35
|
buff_str = LibGSSAPI::UnManagedGssBufferDesc.new
|
33
36
|
buff_str.value = str
|
34
|
-
|
35
|
-
|
37
|
+
# Choose the appropriate mechanism based on the string passed.
|
38
|
+
if (str =~ /[A-Za-z0-9]+\/[^@]+@.+$/)
|
39
|
+
mech = LibGSSAPI::GssOID.gss_c_no_oid
|
40
|
+
else
|
41
|
+
mech = LibGSSAPI.GSS_C_NT_HOSTBASED_SERVICE
|
42
|
+
end
|
36
43
|
name = FFI::MemoryPointer.new :pointer # gss_name_t
|
37
|
-
min_stat = FFI::MemoryPointer.new :
|
44
|
+
min_stat = FFI::MemoryPointer.new :OM_uint32
|
38
45
|
|
39
46
|
maj_stat = LibGSSAPI.gss_import_name(min_stat, buff_str.pointer, mech, name)
|
40
|
-
raise GssApiError, "gss_import_name did not return GSS_S_COMPLETE
|
47
|
+
raise GssApiError.new(maj_stat, min_stat), "gss_import_name did not return GSS_S_COMPLETE" if maj_stat != 0
|
41
48
|
|
42
49
|
LibGSSAPI::GssNameT.new(name.get_pointer(0))
|
43
50
|
end
|
@@ -53,7 +60,7 @@ module GSSAPI
|
|
53
60
|
# @return [String, true] if a continuation flag is set it will return the output token that is needed to send
|
54
61
|
# to the remote host. Otherwise it returns true and the GSS security context has been established.
|
55
62
|
def init_context(in_token = nil, opts = {})
|
56
|
-
min_stat = FFI::MemoryPointer.new :
|
63
|
+
min_stat = FFI::MemoryPointer.new :OM_uint32
|
57
64
|
ctx = (@context.nil? ? LibGSSAPI::GssCtxIdT.gss_c_no_context.address_of : @context.address_of)
|
58
65
|
mech = LibGSSAPI::GssOID.gss_c_no_oid
|
59
66
|
if(opts[:flags])
|
@@ -66,7 +73,7 @@ module GSSAPI
|
|
66
73
|
in_tok = LibGSSAPI::UnManagedGssBufferDesc.new
|
67
74
|
in_tok.value = in_token
|
68
75
|
out_tok = LibGSSAPI::ManagedGssBufferDesc.new
|
69
|
-
ret_flags = FFI::MemoryPointer.new :
|
76
|
+
ret_flags = FFI::MemoryPointer.new :OM_uint32
|
70
77
|
|
71
78
|
|
72
79
|
maj_stat = LibGSSAPI.gss_init_sec_context(min_stat,
|
@@ -83,7 +90,7 @@ module GSSAPI
|
|
83
90
|
ret_flags,
|
84
91
|
nil)
|
85
92
|
|
86
|
-
raise GssApiError, "gss_init_sec_context did not return GSS_S_COMPLETE
|
93
|
+
raise GssApiError.new(maj_stat, min_stat), "gss_init_sec_context did not return GSS_S_COMPLETE" if maj_stat > 1
|
87
94
|
|
88
95
|
@context = LibGSSAPI::GssCtxIdT.new(ctx.get_pointer(0))
|
89
96
|
maj_stat == 1 ? out_tok.value : true
|
@@ -97,7 +104,7 @@ module GSSAPI
|
|
97
104
|
def accept_context(in_token)
|
98
105
|
raise GssApiError, "No credentials yet acquired. Call #{self.class.name}#acquire_credentials first" if @scred.nil?
|
99
106
|
|
100
|
-
min_stat = FFI::MemoryPointer.new :
|
107
|
+
min_stat = FFI::MemoryPointer.new :OM_uint32
|
101
108
|
ctx = (@context.nil? ? LibGSSAPI::GssCtxIdT.gss_c_no_context.address_of : @context.address_of)
|
102
109
|
no_chn_bind = LibGSSAPI::GSS_C_NO_CHANNEL_BINDINGS
|
103
110
|
client = FFI::MemoryPointer.new :pointer # Will hold the initiating client name after the call
|
@@ -105,7 +112,7 @@ module GSSAPI
|
|
105
112
|
in_tok = GSSAPI::LibGSSAPI::UnManagedGssBufferDesc.new
|
106
113
|
in_tok.value = in_token
|
107
114
|
out_tok = GSSAPI::LibGSSAPI::ManagedGssBufferDesc.new
|
108
|
-
ret_flags = FFI::MemoryPointer.new :
|
115
|
+
ret_flags = FFI::MemoryPointer.new :OM_uint32
|
109
116
|
|
110
117
|
maj_stat = LibGSSAPI.gss_accept_sec_context(min_stat,
|
111
118
|
ctx,
|
@@ -118,7 +125,7 @@ module GSSAPI
|
|
118
125
|
ret_flags,
|
119
126
|
nil, nil)
|
120
127
|
|
121
|
-
raise GssApiError, "gss_accept_sec_context did not return GSS_S_COMPLETE
|
128
|
+
raise GssApiError.new(maj_stat, min_stat), "gss_accept_sec_context did not return GSS_S_COMPLETE" if maj_stat > 1
|
122
129
|
|
123
130
|
@context = LibGSSAPI::GssCtxIdT.new(ctx.get_pointer(0))
|
124
131
|
out_tok.length > 0 ? out_tok.value : true
|
@@ -132,7 +139,7 @@ module GSSAPI
|
|
132
139
|
# @return [true] It will return true if everything succeeds and the @scred variable will be set for future methods. If
|
133
140
|
# an error ocurrs an exception will be raised.
|
134
141
|
def acquire_credentials(princ = @int_svc_name, opts = {:usage => :accept})
|
135
|
-
min_stat = FFI::MemoryPointer.new :
|
142
|
+
min_stat = FFI::MemoryPointer.new :OM_uint32
|
136
143
|
scred = FFI::MemoryPointer.new :pointer
|
137
144
|
|
138
145
|
case opts[:usage]
|
@@ -147,7 +154,7 @@ module GSSAPI
|
|
147
154
|
end
|
148
155
|
|
149
156
|
maj_stat = LibGSSAPI.gss_acquire_cred(min_stat, princ, 0, LibGSSAPI::GSS_C_NO_OID_SET, usage, scred, nil, nil)
|
150
|
-
raise GssApiError, "gss_acquire_cred did not return GSS_S_COMPLETE
|
157
|
+
raise GssApiError.new(maj_stat, min_stat), "gss_acquire_cred did not return GSS_S_COMPLETE" if maj_stat != 0
|
151
158
|
|
152
159
|
@scred = LibGSSAPI::GssCredIdT.new(scred.get_pointer(0))
|
153
160
|
true
|
@@ -158,15 +165,15 @@ module GSSAPI
|
|
158
165
|
# @param [Boolean] encrypt Whether or not to encrypt the message or just sign it. The default is to encrypt.
|
159
166
|
# @return [String] The wrapped message. It will raise an exception on error
|
160
167
|
def wrap_message(msg, encrypt = true)
|
161
|
-
min_stat = FFI::MemoryPointer.new :
|
168
|
+
min_stat = FFI::MemoryPointer.new :OM_uint32
|
162
169
|
conf_req = (encrypt ? 1 : 0)
|
163
170
|
qop_req = GSSAPI::LibGSSAPI::GSS_C_QOP_DEFAULT
|
164
171
|
in_buff = GSSAPI::LibGSSAPI::UnManagedGssBufferDesc.new
|
165
172
|
in_buff.value = msg
|
166
|
-
conf_state = FFI::MemoryPointer.new :
|
173
|
+
conf_state = FFI::MemoryPointer.new :OM_uint32
|
167
174
|
out_buff = GSSAPI::LibGSSAPI::ManagedGssBufferDesc.new
|
168
175
|
maj_stat = GSSAPI::LibGSSAPI.gss_wrap(min_stat, @context, conf_req, qop_req, in_buff.pointer, conf_state, out_buff.pointer)
|
169
|
-
raise GssApiError, "Failed to gss_wrap message
|
176
|
+
raise GssApiError.new(maj_stat, min_stat), "Failed to gss_wrap message" if maj_stat != 0
|
170
177
|
out_buff.value
|
171
178
|
end
|
172
179
|
|
@@ -174,16 +181,16 @@ module GSSAPI
|
|
174
181
|
# @param [String] msg The message to unwrap
|
175
182
|
# @param [Boolean] encrypted Whether or not this message was encrypted (true) or just signed (false)
|
176
183
|
def unwrap_message(msg, encrypted = true)
|
177
|
-
min_stat = FFI::MemoryPointer.new :
|
184
|
+
min_stat = FFI::MemoryPointer.new :OM_uint32
|
178
185
|
in_buff = GSSAPI::LibGSSAPI::UnManagedGssBufferDesc.new
|
179
186
|
in_buff.value = msg
|
180
187
|
out_buff = GSSAPI::LibGSSAPI::ManagedGssBufferDesc.new
|
181
188
|
conf_state = FFI::MemoryPointer.new :int
|
182
189
|
conf_state.write_int((encrypted ? 1 : 0))
|
183
|
-
q_op = FFI::MemoryPointer.new :
|
190
|
+
q_op = FFI::MemoryPointer.new :OM_uint32
|
184
191
|
q_op.write_int(0)
|
185
192
|
maj_stat = GSSAPI::LibGSSAPI.gss_unwrap(min_stat, @context, in_buff.pointer, out_buff.pointer, conf_state, q_op)
|
186
|
-
raise GssApiError, "Failed to gss_unwrap message
|
193
|
+
raise GssApiError.new(maj_stat, min_stat), "Failed to gss_unwrap message" if maj_stat != 0
|
187
194
|
out_buff.value
|
188
195
|
end
|
189
196
|
|
@@ -191,7 +198,7 @@ module GSSAPI
|
|
191
198
|
# @param [String] keytab the path to the keytab
|
192
199
|
def set_keytab(keytab)
|
193
200
|
maj_stat = LibGSSAPI.krb5_gss_register_acceptor_identity(keytab)
|
194
|
-
raise GssApiError, "krb5_gss_register_acceptor_identity did not return GSS_S_COMPLETE
|
201
|
+
raise GssApiError.new(maj_stat, min_stat), "krb5_gss_register_acceptor_identity did not return GSS_S_COMPLETE" if maj_stat != 0
|
195
202
|
true
|
196
203
|
end
|
197
204
|
|
@@ -0,0 +1,24 @@
|
|
1
|
+
$: << File.dirname(__FILE__) + '/../../lib/'
|
2
|
+
require 'gssapi'
|
3
|
+
require 'base64'
|
4
|
+
require 'yaml'
|
5
|
+
|
6
|
+
|
7
|
+
describe GSSAPI::Simple, 'Test the Simple GSSAPI interface' do
|
8
|
+
|
9
|
+
before :all do
|
10
|
+
@conf = YAML.load_file "#{File.dirname(__FILE__)}/conf_file.yaml"
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should get the initial context for a client' do
|
14
|
+
gsscli = GSSAPI::Simple.new(@conf[:c_host], @conf[:c_service])
|
15
|
+
token = gsscli.init_context
|
16
|
+
token.should_not be_empty
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should acquire credentials for a server service' do
|
20
|
+
gsscli = GSSAPI::Simple.new(@conf[:s_host], @conf[:s_service], @conf[:keytab])
|
21
|
+
gsscli.acquire_credentials.should be_true
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
$: << File.dirname(__FILE__) + '/../../lib/'
|
2
|
+
require 'gssapi'
|
3
|
+
|
4
|
+
describe GSSAPI::LibGSSAPI::UnManagedGssBufferDesc, 'Unmanaged Buffer Test' do
|
5
|
+
it 'should create a new UnManagedGssBufferDesc and assign to it and test GC' do
|
6
|
+
0.upto 100 do |i|
|
7
|
+
b = GSSAPI::LibGSSAPI::UnManagedGssBufferDesc.new
|
8
|
+
GC.start
|
9
|
+
b.value = 'asdf'
|
10
|
+
end
|
11
|
+
|
12
|
+
# If we get here without any errors we should be golden
|
13
|
+
true.should be_true
|
14
|
+
end
|
15
|
+
end
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: gssapi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 1.0.
|
5
|
+
version: 1.0.2
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Dan Wanek
|
@@ -10,8 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-
|
14
|
-
default_executable:
|
13
|
+
date: 2011-09-10 00:00:00 Z
|
15
14
|
dependencies:
|
16
15
|
- !ruby/object:Gem::Dependency
|
17
16
|
name: ffi
|
@@ -48,7 +47,8 @@ files:
|
|
48
47
|
- lib/gssapi/lib_gssapi_loader.rb
|
49
48
|
- lib/gssapi/simple.rb
|
50
49
|
- preamble
|
51
|
-
|
50
|
+
- test/spec/gssapi_simple_spec.rb
|
51
|
+
- test/spec/test_buffer_spec.rb
|
52
52
|
homepage: http://github.com/zenchild/gssapi
|
53
53
|
licenses: []
|
54
54
|
|
@@ -75,7 +75,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
75
75
|
requirements: []
|
76
76
|
|
77
77
|
rubyforge_project:
|
78
|
-
rubygems_version: 1.
|
78
|
+
rubygems_version: 1.8.10
|
79
79
|
signing_key:
|
80
80
|
specification_version: 3
|
81
81
|
summary: A FFI wrapper around the system GSSAPI library.
|