gssapi 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+