gssapi 0.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.
@@ -0,0 +1,196 @@
1
+ #############################################################################
2
+ # Copyright © 2010 Dan Wanek <dan.wanek@gmail.com>
3
+ #
4
+ #
5
+ # This file is part of the Ruby GSSAPI library.
6
+ #
7
+ # GSSAPI is free software: you can redistribute it and/or
8
+ # modify it under the terms of the GNU General Public License as published
9
+ # by the Free Software Foundation, either version 3 of the License, or (at
10
+ # your option) any later version.
11
+ #
12
+ # GSSAPI is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
15
+ # Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU General Public License along
18
+ # with GSSAPI. If not, see <http://www.gnu.org/licenses/>.
19
+ #############################################################################
20
+ module GSSAPI
21
+
22
+ # This class is a simple wrapper around the most common usage of GSSAPI. If you are looking at doing
23
+ # something a bit more advanced you may want to check out the LibGSSAPI module.
24
+ class Simple
25
+
26
+ # Initialize a new GSSAPI::Simple object
27
+ # @param [String] host_name the fully qualified host name
28
+ # @param [String] service_name the service name. This can either be in the form svc@example.org
29
+ # or just svc. If there is no '@example.org' part the host_name will be appended. If no
30
+ # service_name is given at all the default service of 'host' will be used.
31
+ def initialize(host_name, service_name=nil, keytab=nil)
32
+ @host = host_name
33
+ @service = service_name.nil? ? "host@#{@host}" : (service_name.include?('@') ? service_name : "#{service_name}@#{@host}")
34
+ @int_svc_name = import_name(@service)
35
+ @context = nil # the security context
36
+ @scred = nil # the service credentials. really only used for the server-side via acquire_credentials
37
+ set_keytab(keytab) unless keytab.nil?
38
+ end
39
+
40
+
41
+ # Convert a String to a GSSAPI usable buffer (gss_buffer_desc)
42
+ # @param [String] str the string to convert
43
+ def import_name(str)
44
+ buff_str = LibGSSAPI::GssBufferDesc.new
45
+ buff_str.value = str
46
+ name = FFI::MemoryPointer.new :pointer # gss_name_t
47
+ min_stat = FFI::MemoryPointer.new :uint32
48
+
49
+ maj_stat = LibGSSAPI.gss_import_name(min_stat, buff_str.pointer, LibGSSAPI.GSS_C_NT_HOSTBASED_SERVICE, name)
50
+ raise GssApiError, "gss_import_name did not return GSS_S_COMPLETE. Error code: maj: #{maj_stat}, min: #{min_stat.read_int}" if maj_stat != 0
51
+
52
+ LibGSSAPI::GssNameT.new(name.get_pointer(0))
53
+ end
54
+
55
+ # Initialize the GSS security context (client initiator). If there was a previous call that issued a
56
+ # continue you can pass the continuation token in via the token param.
57
+ # @param [String] in_token an input token sent from the remote service in a continuation.
58
+ # @return [String, true] if a continuation flag is set it will return the output token that is needed to send
59
+ # to the remote host. Otherwise it returns true and the GSS security context has been established.
60
+ def init_context(in_token = nil)
61
+ min_stat = FFI::MemoryPointer.new :uint32
62
+ ctx = (@context.nil? ? LibGSSAPI::GssCtxIdT.gss_c_no_context.address_of : @context.address_of)
63
+ mech = LibGSSAPI::GssOID.gss_c_no_oid
64
+ in_tok = LibGSSAPI::GssBufferDesc.new
65
+ in_tok.value = in_token
66
+ out_tok = LibGSSAPI::GssBufferDesc.new
67
+ out_tok.value = nil
68
+
69
+
70
+ maj_stat = LibGSSAPI.gss_init_sec_context(min_stat,
71
+ nil,
72
+ ctx,
73
+ @int_svc_name,
74
+ mech,
75
+ (LibGSSAPI::GSS_C_MUTUAL_FLAG | LibGSSAPI::GSS_C_SEQUENCE_FLAG),
76
+ 0,
77
+ nil,
78
+ in_tok.pointer,
79
+ nil,
80
+ out_tok.pointer,
81
+ nil,
82
+ nil)
83
+
84
+ raise GssApiError, "gss_init_sec_context did not return GSS_S_COMPLETE. Error code: maj: #{maj_stat}, min: #{min_stat.read_int}" if maj_stat > 1
85
+
86
+ @context = LibGSSAPI::GssCtxIdT.new(ctx.get_pointer(0))
87
+ maj_stat == 1 ? out_tok.value : true
88
+ end
89
+
90
+
91
+ # Accept a security context that was initiated by a remote peer.
92
+ # @param [String] in_token The token sent by the remote client to initiate the context
93
+ # @return [String, true] If this is part of a continuation it will return a token to be passed back to the remote
94
+ # otherwise it will simply return true.
95
+ def accept_context(in_token)
96
+ raise GssApiError, "No credentials yet acquired. Call #{self.class.name}#acquire_credentials first" if @scred.nil?
97
+
98
+ min_stat = FFI::MemoryPointer.new :uint32
99
+ ctx = (@context.nil? ? LibGSSAPI::GssCtxIdT.gss_c_no_context.address_of : @context.address_of)
100
+ no_chn_bind = LibGSSAPI::GSS_C_NO_CHANNEL_BINDINGS
101
+ client = FFI::MemoryPointer.new :pointer # Will hold the initiating client name after the call
102
+ mech = FFI::MemoryPointer.new :pointer # Will hold the mech being used after the call
103
+ in_tok = GSSAPI::LibGSSAPI::GssBufferDesc.new
104
+ in_tok.value = in_token
105
+ out_tok = GSSAPI::LibGSSAPI::GssBufferDesc.new
106
+ out_tok.value = nil
107
+ maj_stat = LibGSSAPI.gss_accept_sec_context(min_stat,
108
+ ctx,
109
+ @scred,
110
+ in_tok.pointer,
111
+ no_chn_bind,
112
+ client,
113
+ mech,
114
+ out_tok.pointer,
115
+ nil, nil, nil)
116
+
117
+ raise GssApiError, "gss_accept_sec_context did not return GSS_S_COMPLETE. Error code: maj: #{maj_stat}, min: #{min_stat.read_int}" if maj_stat > 1
118
+
119
+ @context = LibGSSAPI::GssCtxIdT.new(ctx.get_pointer(0))
120
+ out_tok.length > 0 ? out_tok.value : true
121
+ end
122
+
123
+
124
+ # Acquire security credentials. This does not log you in. It grabs the credentials from a cred cache or keytab.
125
+ # @param [Hash] opts options to pass to the gss_acquire_cred function.
126
+ # @option opts [String] :usage The credential usage type ('accept', 'initiate', 'both'). It defaults to 'accept' since
127
+ # this method is most usually called on the server only.
128
+ # @return [true] It will return true if everything succeeds and the @scred variable will be set for future methods. If
129
+ # an error ocurrs an exception will be raised.
130
+ def acquire_credentials(opts = {:usage => 'accept'})
131
+ min_stat = FFI::MemoryPointer.new :uint32
132
+ scred = FFI::MemoryPointer.new :pointer
133
+
134
+ case opts[:usage]
135
+ when 'accept'
136
+ usage = LibGSSAPI::GSS_C_ACCEPT
137
+ when 'initiate'
138
+ usage = LibGSSAPI::GSS_C_INITIATE
139
+ when 'both'
140
+ usage = LibGSSAPI::GSS_C_BOTH
141
+ else
142
+ raise GssApiError, "Bad option passed to #{self.class.name}#acquire_credentials"
143
+ end
144
+
145
+ maj_stat = LibGSSAPI.gss_acquire_cred(min_stat, @int_svc_name, 0, LibGSSAPI::GSS_C_NO_OID_SET, usage, scred, nil, nil)
146
+ raise GssApiError, "gss_acquire_cred did not return GSS_S_COMPLETE. Error code: maj: #{maj_stat}, min: #{min_stat.read_int}" if maj_stat != 0
147
+
148
+ @scred = LibGSSAPI::GssCredIdT.new(scred.get_pointer(0))
149
+ true
150
+ end
151
+
152
+ # Wrap a message using gss_wrap. It can either encrypt the message (confidentiality) or simply sign it (integrity).
153
+ # @param [String] msg The message to wrap
154
+ # @param [Boolean] encrypt Whether or not to encrypt the message or just sign it. The default is to encrypt.
155
+ # @return [String] The wrapped message. It will raise an exception on error
156
+ def wrap_message(msg, encrypt = true)
157
+ min_stat = FFI::MemoryPointer.new :uint32
158
+ conf_req = (encrypt ? 1 : 0)
159
+ qop_req = GSSAPI::LibGSSAPI::GSS_C_QOP_DEFAULT
160
+ in_buff = GSSAPI::LibGSSAPI::GssBufferDesc.new
161
+ in_buff.value = msg
162
+ conf_state = FFI::MemoryPointer.new :uint32
163
+ out_buff = GSSAPI::LibGSSAPI::GssBufferDesc.new
164
+ out_buff.value = nil
165
+ maj_stat = GSSAPI::LibGSSAPI.gss_wrap(min_stat, @context, conf_req, qop_req, in_buff.pointer, conf_state, out_buff.pointer)
166
+ raise GssApiError, "Failed to gss_wrap message. Error code: maj: #{maj_stat}, min: #{min_stat.read_int}" if maj_stat != 0
167
+ out_buff.value
168
+ end
169
+
170
+ # Unwrap a message previously wrapped with gss_wrap.
171
+ # @param [String] msg The message to unwrap
172
+ # @param [Boolean] encrypted Whether or not this message was encrypted (true) or just signed (false)
173
+ def unwrap_message(msg, encrypted = true)
174
+ min_stat = FFI::MemoryPointer.new :uint32
175
+ in_buff = GSSAPI::LibGSSAPI::GssBufferDesc.new
176
+ in_buff.value = msg
177
+ out_buff = GSSAPI::LibGSSAPI::GssBufferDesc.new
178
+ conf_state = FFI::MemoryPointer.new :int
179
+ conf_state.write_int((encrypted ? 1 : 0))
180
+ q_op = FFI::MemoryPointer.new :uint32
181
+ q_op.write_int(0)
182
+ maj_stat = GSSAPI::LibGSSAPI.gss_unwrap(min_stat, @context, in_buff.pointer, out_buff.pointer, conf_state, q_op)
183
+ raise GssApiError, "Failed to gss_unwrap message. Error code: maj: #{maj_stat}, min: #{min_stat.read_int}" if maj_stat != 0
184
+ out_buff.value
185
+ end
186
+
187
+ # Add a path to a custom keytab file
188
+ # @param [String] keytab the path to the keytab
189
+ def set_keytab(keytab)
190
+ maj_stat = LibGSSAPI.krb5_gss_register_acceptor_identity(keytab)
191
+ raise GssApiError, "krb5_gss_register_acceptor_identity did not return GSS_S_COMPLETE. Error code: maj: #{maj_stat}, min: #{min_stat.read_int}" if maj_stat != 0
192
+ true
193
+ end
194
+
195
+ end # Simple
196
+ end # GSSAPI
@@ -0,0 +1,19 @@
1
+ #############################################################################
2
+ # Copyright © 2010 Dan Wanek <dan.wanek@gmail.com>
3
+ #
4
+ #
5
+ # This file is part of the Ruby GSSAPI library.
6
+ #
7
+ # GSSAPI is free software: you can redistribute it and/or
8
+ # modify it under the terms of the GNU General Public License as published
9
+ # by the Free Software Foundation, either version 3 of the License, or (at
10
+ # your option) any later version.
11
+ #
12
+ # GSSAPI is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
15
+ # Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU General Public License along
18
+ # with GSSAPI. If not, see <http://www.gnu.org/licenses/>.
19
+ #############################################################################
metadata ADDED
@@ -0,0 +1,95 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gssapi
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 2
9
+ version: 0.0.2
10
+ platform: ruby
11
+ authors:
12
+ - Dan Wanek
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-12-16 00:00:00 -06:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: ffi
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 1
30
+ - 0
31
+ - 1
32
+ version: 1.0.1
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ description: " A FFI wrapper around the system GSSAPI library. Please make sure and read the\n Yard docs or standard GSSAPI documentation if you have any questions.\n \n There is also a class called GSSAPI::Simple that wraps many of the common features\n used for GSSAPI.\n"
36
+ email: dan.wanek@gmail.com
37
+ executables: []
38
+
39
+ extensions: []
40
+
41
+ extra_rdoc_files:
42
+ - README.textile
43
+ - COPYING.txt
44
+ files:
45
+ - COPYING.txt
46
+ - README.textile
47
+ - Rakefile
48
+ - VERSION
49
+ - examples/gss_client.rb
50
+ - examples/gss_server.rb
51
+ - gssapi.gemspec
52
+ - lib/gssapi.rb
53
+ - lib/gssapi/exceptions.rb
54
+ - lib/gssapi/lib_gssapi.rb
55
+ - lib/gssapi/simple.rb
56
+ - preamble
57
+ has_rdoc: true
58
+ homepage: http://github.com/zenchild/gssapi
59
+ licenses: []
60
+
61
+ post_install_message:
62
+ rdoc_options:
63
+ - -x
64
+ - test/
65
+ - -x
66
+ - examples/
67
+ require_paths:
68
+ - lib
69
+ required_ruby_version: !ruby/object:Gem::Requirement
70
+ none: false
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ segments:
75
+ - 1
76
+ - 9
77
+ - 1
78
+ version: 1.9.1
79
+ required_rubygems_version: !ruby/object:Gem::Requirement
80
+ none: false
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ segments:
85
+ - 0
86
+ version: "0"
87
+ requirements: []
88
+
89
+ rubyforge_project:
90
+ rubygems_version: 1.3.7
91
+ signing_key:
92
+ specification_version: 3
93
+ summary: A FFI wrapper around the system GSSAPI library.
94
+ test_files: []
95
+