net-ssh-kerberos 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE CHANGED
@@ -1,20 +1,339 @@
1
- Copyright (c) 2009 Joe Khoobyar
2
-
3
- Permission is hereby granted, free of charge, to any person obtaining
4
- a copy of this software and associated documentation files (the
5
- "Software"), to deal in the Software without restriction, including
6
- without limitation the rights to use, copy, modify, merge, publish,
7
- distribute, sublicense, and/or sell copies of the Software, and to
8
- permit persons to whom the Software is furnished to do so, subject to
9
- the following conditions:
10
-
11
- The above copyright notice and this permission notice shall be
12
- included in all copies or substantial portions of the Software.
13
-
14
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1
+ GNU GENERAL PUBLIC LICENSE
2
+ Version 2, June 1991
3
+
4
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
5
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6
+ Everyone is permitted to copy and distribute verbatim copies
7
+ of this license document, but changing it is not allowed.
8
+
9
+ Preamble
10
+
11
+ The licenses for most software are designed to take away your
12
+ freedom to share and change it. By contrast, the GNU General Public
13
+ License is intended to guarantee your freedom to share and change free
14
+ software--to make sure the software is free for all its users. This
15
+ General Public License applies to most of the Free Software
16
+ Foundation's software and to any other program whose authors commit to
17
+ using it. (Some other Free Software Foundation software is covered by
18
+ the GNU Lesser General Public License instead.) You can apply it to
19
+ your programs, too.
20
+
21
+ When we speak of free software, we are referring to freedom, not
22
+ price. Our General Public Licenses are designed to make sure that you
23
+ have the freedom to distribute copies of free software (and charge for
24
+ this service if you wish), that you receive source code or can get it
25
+ if you want it, that you can change the software or use pieces of it
26
+ in new free programs; and that you know you can do these things.
27
+
28
+ To protect your rights, we need to make restrictions that forbid
29
+ anyone to deny you these rights or to ask you to surrender the rights.
30
+ These restrictions translate to certain responsibilities for you if you
31
+ distribute copies of the software, or if you modify it.
32
+
33
+ For example, if you distribute copies of such a program, whether
34
+ gratis or for a fee, you must give the recipients all the rights that
35
+ you have. You must make sure that they, too, receive or can get the
36
+ source code. And you must show them these terms so they know their
37
+ rights.
38
+
39
+ We protect your rights with two steps: (1) copyright the software, and
40
+ (2) offer you this license which gives you legal permission to copy,
41
+ distribute and/or modify the software.
42
+
43
+ Also, for each author's protection and ours, we want to make certain
44
+ that everyone understands that there is no warranty for this free
45
+ software. If the software is modified by someone else and passed on, we
46
+ want its recipients to know that what they have is not the original, so
47
+ that any problems introduced by others will not reflect on the original
48
+ authors' reputations.
49
+
50
+ Finally, any free program is threatened constantly by software
51
+ patents. We wish to avoid the danger that redistributors of a free
52
+ program will individually obtain patent licenses, in effect making the
53
+ program proprietary. To prevent this, we have made it clear that any
54
+ patent must be licensed for everyone's free use or not licensed at all.
55
+
56
+ The precise terms and conditions for copying, distribution and
57
+ modification follow.
58
+
59
+ GNU GENERAL PUBLIC LICENSE
60
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61
+
62
+ 0. This License applies to any program or other work which contains
63
+ a notice placed by the copyright holder saying it may be distributed
64
+ under the terms of this General Public License. The "Program", below,
65
+ refers to any such program or work, and a "work based on the Program"
66
+ means either the Program or any derivative work under copyright law:
67
+ that is to say, a work containing the Program or a portion of it,
68
+ either verbatim or with modifications and/or translated into another
69
+ language. (Hereinafter, translation is included without limitation in
70
+ the term "modification".) Each licensee is addressed as "you".
71
+
72
+ Activities other than copying, distribution and modification are not
73
+ covered by this License; they are outside its scope. The act of
74
+ running the Program is not restricted, and the output from the Program
75
+ is covered only if its contents constitute a work based on the
76
+ Program (independent of having been made by running the Program).
77
+ Whether that is true depends on what the Program does.
78
+
79
+ 1. You may copy and distribute verbatim copies of the Program's
80
+ source code as you receive it, in any medium, provided that you
81
+ conspicuously and appropriately publish on each copy an appropriate
82
+ copyright notice and disclaimer of warranty; keep intact all the
83
+ notices that refer to this License and to the absence of any warranty;
84
+ and give any other recipients of the Program a copy of this License
85
+ along with the Program.
86
+
87
+ You may charge a fee for the physical act of transferring a copy, and
88
+ you may at your option offer warranty protection in exchange for a fee.
89
+
90
+ 2. You may modify your copy or copies of the Program or any portion
91
+ of it, thus forming a work based on the Program, and copy and
92
+ distribute such modifications or work under the terms of Section 1
93
+ above, provided that you also meet all of these conditions:
94
+
95
+ a) You must cause the modified files to carry prominent notices
96
+ stating that you changed the files and the date of any change.
97
+
98
+ b) You must cause any work that you distribute or publish, that in
99
+ whole or in part contains or is derived from the Program or any
100
+ part thereof, to be licensed as a whole at no charge to all third
101
+ parties under the terms of this License.
102
+
103
+ c) If the modified program normally reads commands interactively
104
+ when run, you must cause it, when started running for such
105
+ interactive use in the most ordinary way, to print or display an
106
+ announcement including an appropriate copyright notice and a
107
+ notice that there is no warranty (or else, saying that you provide
108
+ a warranty) and that users may redistribute the program under
109
+ these conditions, and telling the user how to view a copy of this
110
+ License. (Exception: if the Program itself is interactive but
111
+ does not normally print such an announcement, your work based on
112
+ the Program is not required to print an announcement.)
113
+
114
+ These requirements apply to the modified work as a whole. If
115
+ identifiable sections of that work are not derived from the Program,
116
+ and can be reasonably considered independent and separate works in
117
+ themselves, then this License, and its terms, do not apply to those
118
+ sections when you distribute them as separate works. But when you
119
+ distribute the same sections as part of a whole which is a work based
120
+ on the Program, the distribution of the whole must be on the terms of
121
+ this License, whose permissions for other licensees extend to the
122
+ entire whole, and thus to each and every part regardless of who wrote it.
123
+
124
+ Thus, it is not the intent of this section to claim rights or contest
125
+ your rights to work written entirely by you; rather, the intent is to
126
+ exercise the right to control the distribution of derivative or
127
+ collective works based on the Program.
128
+
129
+ In addition, mere aggregation of another work not based on the Program
130
+ with the Program (or with a work based on the Program) on a volume of
131
+ a storage or distribution medium does not bring the other work under
132
+ the scope of this License.
133
+
134
+ 3. You may copy and distribute the Program (or a work based on it,
135
+ under Section 2) in object code or executable form under the terms of
136
+ Sections 1 and 2 above provided that you also do one of the following:
137
+
138
+ a) Accompany it with the complete corresponding machine-readable
139
+ source code, which must be distributed under the terms of Sections
140
+ 1 and 2 above on a medium customarily used for software interchange; or,
141
+
142
+ b) Accompany it with a written offer, valid for at least three
143
+ years, to give any third party, for a charge no more than your
144
+ cost of physically performing source distribution, a complete
145
+ machine-readable copy of the corresponding source code, to be
146
+ distributed under the terms of Sections 1 and 2 above on a medium
147
+ customarily used for software interchange; or,
148
+
149
+ c) Accompany it with the information you received as to the offer
150
+ to distribute corresponding source code. (This alternative is
151
+ allowed only for noncommercial distribution and only if you
152
+ received the program in object code or executable form with such
153
+ an offer, in accord with Subsection b above.)
154
+
155
+ The source code for a work means the preferred form of the work for
156
+ making modifications to it. For an executable work, complete source
157
+ code means all the source code for all modules it contains, plus any
158
+ associated interface definition files, plus the scripts used to
159
+ control compilation and installation of the executable. However, as a
160
+ special exception, the source code distributed need not include
161
+ anything that is normally distributed (in either source or binary
162
+ form) with the major components (compiler, kernel, and so on) of the
163
+ operating system on which the executable runs, unless that component
164
+ itself accompanies the executable.
165
+
166
+ If distribution of executable or object code is made by offering
167
+ access to copy from a designated place, then offering equivalent
168
+ access to copy the source code from the same place counts as
169
+ distribution of the source code, even though third parties are not
170
+ compelled to copy the source along with the object code.
171
+
172
+ 4. You may not copy, modify, sublicense, or distribute the Program
173
+ except as expressly provided under this License. Any attempt
174
+ otherwise to copy, modify, sublicense or distribute the Program is
175
+ void, and will automatically terminate your rights under this License.
176
+ However, parties who have received copies, or rights, from you under
177
+ this License will not have their licenses terminated so long as such
178
+ parties remain in full compliance.
179
+
180
+ 5. You are not required to accept this License, since you have not
181
+ signed it. However, nothing else grants you permission to modify or
182
+ distribute the Program or its derivative works. These actions are
183
+ prohibited by law if you do not accept this License. Therefore, by
184
+ modifying or distributing the Program (or any work based on the
185
+ Program), you indicate your acceptance of this License to do so, and
186
+ all its terms and conditions for copying, distributing or modifying
187
+ the Program or works based on it.
188
+
189
+ 6. Each time you redistribute the Program (or any work based on the
190
+ Program), the recipient automatically receives a license from the
191
+ original licensor to copy, distribute or modify the Program subject to
192
+ these terms and conditions. You may not impose any further
193
+ restrictions on the recipients' exercise of the rights granted herein.
194
+ You are not responsible for enforcing compliance by third parties to
195
+ this License.
196
+
197
+ 7. If, as a consequence of a court judgment or allegation of patent
198
+ infringement or for any other reason (not limited to patent issues),
199
+ conditions are imposed on you (whether by court order, agreement or
200
+ otherwise) that contradict the conditions of this License, they do not
201
+ excuse you from the conditions of this License. If you cannot
202
+ distribute so as to satisfy simultaneously your obligations under this
203
+ License and any other pertinent obligations, then as a consequence you
204
+ may not distribute the Program at all. For example, if a patent
205
+ license would not permit royalty-free redistribution of the Program by
206
+ all those who receive copies directly or indirectly through you, then
207
+ the only way you could satisfy both it and this License would be to
208
+ refrain entirely from distribution of the Program.
209
+
210
+ If any portion of this section is held invalid or unenforceable under
211
+ any particular circumstance, the balance of the section is intended to
212
+ apply and the section as a whole is intended to apply in other
213
+ circumstances.
214
+
215
+ It is not the purpose of this section to induce you to infringe any
216
+ patents or other property right claims or to contest validity of any
217
+ such claims; this section has the sole purpose of protecting the
218
+ integrity of the free software distribution system, which is
219
+ implemented by public license practices. Many people have made
220
+ generous contributions to the wide range of software distributed
221
+ through that system in reliance on consistent application of that
222
+ system; it is up to the author/donor to decide if he or she is willing
223
+ to distribute software through any other system and a licensee cannot
224
+ impose that choice.
225
+
226
+ This section is intended to make thoroughly clear what is believed to
227
+ be a consequence of the rest of this License.
228
+
229
+ 8. If the distribution and/or use of the Program is restricted in
230
+ certain countries either by patents or by copyrighted interfaces, the
231
+ original copyright holder who places the Program under this License
232
+ may add an explicit geographical distribution limitation excluding
233
+ those countries, so that distribution is permitted only in or among
234
+ countries not thus excluded. In such case, this License incorporates
235
+ the limitation as if written in the body of this License.
236
+
237
+ 9. The Free Software Foundation may publish revised and/or new versions
238
+ of the General Public License from time to time. Such new versions will
239
+ be similar in spirit to the present version, but may differ in detail to
240
+ address new problems or concerns.
241
+
242
+ Each version is given a distinguishing version number. If the Program
243
+ specifies a version number of this License which applies to it and "any
244
+ later version", you have the option of following the terms and conditions
245
+ either of that version or of any later version published by the Free
246
+ Software Foundation. If the Program does not specify a version number of
247
+ this License, you may choose any version ever published by the Free Software
248
+ Foundation.
249
+
250
+ 10. If you wish to incorporate parts of the Program into other free
251
+ programs whose distribution conditions are different, write to the author
252
+ to ask for permission. For software which is copyrighted by the Free
253
+ Software Foundation, write to the Free Software Foundation; we sometimes
254
+ make exceptions for this. Our decision will be guided by the two goals
255
+ of preserving the free status of all derivatives of our free software and
256
+ of promoting the sharing and reuse of software generally.
257
+
258
+ NO WARRANTY
259
+
260
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261
+ FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262
+ OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263
+ PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264
+ OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266
+ TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267
+ PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268
+ REPAIR OR CORRECTION.
269
+
270
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271
+ WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272
+ REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273
+ INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274
+ OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275
+ TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276
+ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277
+ PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278
+ POSSIBILITY OF SUCH DAMAGES.
279
+
280
+ END OF TERMS AND CONDITIONS
281
+
282
+ How to Apply These Terms to Your New Programs
283
+
284
+ If you develop a new program, and you want it to be of the greatest
285
+ possible use to the public, the best way to achieve this is to make it
286
+ free software which everyone can redistribute and change under these terms.
287
+
288
+ To do so, attach the following notices to the program. It is safest
289
+ to attach them to the start of each source file to most effectively
290
+ convey the exclusion of warranty; and each file should have at least
291
+ the "copyright" line and a pointer to where the full notice is found.
292
+
293
+ <one line to give the program's name and a brief idea of what it does.>
294
+ Copyright (C) <year> <name of author>
295
+
296
+ This program is free software; you can redistribute it and/or modify
297
+ it under the terms of the GNU General Public License as published by
298
+ the Free Software Foundation; either version 2 of the License, or
299
+ (at your option) any later version.
300
+
301
+ This program is distributed in the hope that it will be useful,
302
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
303
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
304
+ GNU General Public License for more details.
305
+
306
+ You should have received a copy of the GNU General Public License along
307
+ with this program; if not, write to the Free Software Foundation, Inc.,
308
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
309
+
310
+ Also add information on how to contact you by electronic and paper mail.
311
+
312
+ If the program is interactive, make it output a short notice like this
313
+ when it starts in an interactive mode:
314
+
315
+ Gnomovision version 69, Copyright (C) year name of author
316
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
317
+ This is free software, and you are welcome to redistribute it
318
+ under certain conditions; type `show c' for details.
319
+
320
+ The hypothetical commands `show w' and `show c' should show the appropriate
321
+ parts of the General Public License. Of course, the commands you use may
322
+ be called something other than `show w' and `show c'; they could even be
323
+ mouse-clicks or menu items--whatever suits your program.
324
+
325
+ You should also get your employer (if you work as a programmer) or your
326
+ school, if any, to sign a "copyright disclaimer" for the program, if
327
+ necessary. Here is a sample; alter the names:
328
+
329
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
330
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
331
+
332
+ <signature of Ty Coon>, 1 April 1989
333
+ Ty Coon, President of Vice
334
+
335
+ This General Public License does not permit incorporating your program into
336
+ proprietary programs. If your program is a subroutine library, you may
337
+ consider it more useful to permit linking proprietary applications with the
338
+ library. If this is what you want to do, use the GNU Lesser General
339
+ Public License instead of this License.
@@ -1,10 +1,27 @@
1
1
  = net-ssh-kerberos
2
2
 
3
- Adds Kerberos support to Net::SSH.
3
+ Add Kerberos (password-less) authentication capabilities to Net::SSH, without the need for modifying Net::SSH source code.
4
4
 
5
- Windows support uses Microsoft SSPI for Kerberos integration.
5
+ This is a great way to help get Capistrano to be accepted in mid-to-large size enterprises with strict security rules.
6
6
 
7
- Kerberos support for UNIX and OS X coming soon.
7
+ No more getting locked out of the network because you mis-typed your password - even if your company prohibits
8
+ public key or host-based authentication. If your organization uses Kerberos (many mid-to-large size corporations do),
9
+ you can use this package to get password-less authentication without breaking your company's security guidelines.
10
+
11
+ == How to use with Capistrano
12
+
13
+ Add the following lines to the top of your Capfile (the relevant :auth_method is "gssapi-with-mic")
14
+
15
+ require 'net/ssh/kerberos'
16
+ set :ssh_options, { :auth_methods => %w(gssapi-with-mic publickey hostbased password keyboard-interactive) }
17
+
18
+
19
+ == Supported Platforms
20
+
21
+ - UNIX systems use the GSSAPI for Kerberos 5 integration. (tested on RedHat Linux)
22
+ - Windows systems use Microsoft SSPI for Kerberos 5 integration. (tested on Windows XP)
23
+ - Supports enterprise-level Kerberos-based security (tested with Centrify DC)
24
+ - Cross-forest authentication is supported, including mixed environment (tested with Centrify DC in a mixed Windows/Linux environment)
8
25
 
9
26
  == Copyright
10
27
 
@@ -1,4 +1,4 @@
1
1
  ---
2
2
  :major: 0
3
3
  :minor: 1
4
- :patch: 2
4
+ :patch: 3
@@ -12,7 +12,6 @@ module Net
12
12
 
13
13
  # OID 1.2.840.113554.1.2.2 - Kerberos 5 (RFC 1964)
14
14
  SUPPORTED_OID = "\x06\x09\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"
15
- #[ 0x6, 0x9, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x1, 0x2, 0x2 ].pack("C*")
16
15
 
17
16
  # Attempts to perform gssapi-with-mic Kerberos authentication
18
17
  def authenticate(next_service, username, password=nil)
@@ -1,6 +1,7 @@
1
1
  require 'net/ssh'
2
2
  require 'net/ssh/kerberos/constants'
3
3
  #require 'net/ssh/kerberos/kex'
4
+
4
5
  if RUBY_PLATFORM.include?('win') && ! RUBY_PLATFORM.include?('dar'); then
5
6
  begin
6
7
  require 'net/ssh/kerberos/sspi'
@@ -12,7 +13,7 @@ if RUBY_PLATFORM.include?('win') && ! RUBY_PLATFORM.include?('dar'); then
12
13
  end
13
14
  end
14
15
  end
15
- require 'net/ssh/kerberos/gss' unless defined?(Net::SSH::Kerberos::SSPI::Context)
16
+ require 'net/ssh/kerberos/gss'
16
17
  require 'net/ssh/authentication/methods/gssapi_with_mic'
17
18
 
18
19
  module Net
@@ -0,0 +1,71 @@
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
@@ -24,7 +24,7 @@ module Net; module SSH; module Kerberos
24
24
  USERAUTH_GSSAPI_ERROR = 64
25
25
  USERAUTH_GSSAPI_ERRTOK = 65
26
26
  USERAUTH_GSSAPI_MIC = 66
27
-
27
+
28
28
  end
29
29
  end; end; end
30
30
 
@@ -1,7 +1,9 @@
1
- $stderr.puts "warning: Kerberos support for non-Windows systems is not yet implemented."
1
+ if ! defined? Net::SSH::Kerberos::SSPI::Context
2
+ $stderr.puts "warning: Kerberos support using GSSAPI is not fully tested."
3
+ end
2
4
 
3
- require 'net/ssh/kerberos/gss/api'
4
- require 'net/ssh/kerberos/gss/context'
5
-
6
- module Net; module SSH; module Kerberos; module GSS
7
- end; end; end; end
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,4 +1,163 @@
1
+ require 'dl/import'
2
+ require 'dl/struct'
1
3
 
2
- module Net; module SSH; module Kerberos; module GSS; class API
4
+ module Net; module SSH; module Kerberos; module GSS;
3
5
 
4
- end; end; end; end; end
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,7 +1,115 @@
1
+ require 'net/ssh/kerberos/common/context'
1
2
  require 'net/ssh/kerberos/gss/api'
2
3
 
3
- module Net; module SSH; module Kerberos; module GSS; class Context
4
+ module Net; module SSH; module Kerberos; module GSS; class Context < Common::Context
4
5
 
5
- class GeneralError < StandardError; end
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
6
114
 
7
115
  end; end; end; end; end
@@ -1,44 +1,9 @@
1
+ require 'net/ssh/kerberos/common/context'
1
2
  require 'net/ssh/kerberos/sspi/api'
2
3
 
3
- module Net; module SSH; module Kerberos; module SSPI; class Context
4
-
5
- class GeneralError < StandardError; end
4
+ module Net; module SSH; module Kerberos; module SSPI; class Context < Common::Context
6
5
 
7
6
  include Win32::SSPI
8
-
9
- attr_reader :cred_name, :cred_krb_name, :server_name, :server_krb_name
10
-
11
- def create(user, host)
12
- dispose if @credentials or @handle
13
- creds = CredHandle.new
14
- ts = TimeStamp.new
15
-
16
- result = API::AcquireCredentialsHandle nil, "Kerberos", SECPKG_CRED_OUTBOUND, nil, nil, nil, nil, creds, ts
17
- result.ok? or raise GeneralError, "Error acquiring credentials: #{result}"
18
-
19
- buff = "\0\0\0\0"
20
- result = API::QueryCredentialsAttributes creds, SECPKG_CRED_ATTR_NAMES, buff
21
- if result.ok?
22
- names = buff.to_ptr.ptr
23
- begin
24
- @cred_name = names.to_s.sub(/^[^\\\/]*[\\\/]/, '')
25
- @cred_krb_name = @cred_name.gsub('@', '/');
26
- @server_name = Socket.gethostbyname(host)[0]
27
- @server_krb_name = "host/" + @server_name
28
-
29
- z = (user.include?('@') ? user.gsub('@','/') : user+'/')
30
- unless z.downcase == @cred_krb_name[0,z.length].downcase
31
- raise GeneralError, "Credentials mismatch: current is #{@cred_name}, requested is #{user}"
32
- end
33
- @credentials = creds
34
- ensure
35
- @credentials or API::FreeCredentialsHandle creds
36
- API::FreeContextBuffer names
37
- end
38
- end
39
- end
40
-
41
- def credentials?; ! @credentials.nil? end
42
7
 
43
8
  def init(token=nil)
44
9
  ctx = CtxtHandle.new
@@ -54,34 +19,58 @@ module Net; module SSH; module Kerberos; module SSPI; class Context
54
19
  if result.failure?
55
20
  input.token and raise GeneralError, "Error initializing security context: #{result} #{input.inspect}"
56
21
  end
57
- @state = { :handle => ctx, :result => result, :token => output.token, :stamp => ts }
22
+ @state = State.new(ctx, result, output.token, ts)
58
23
  if result.complete?
59
24
  result = API::QueryContextAttributes ctx, SECPKG_ATTR_SIZES, @sizes=SecPkgSizes.new
60
- @handle = @state[:handle]
25
+ @handle = @state.handle
61
26
  end
62
- @state[:token]
63
- end
64
-
65
- def established?
66
- ! @handle.nil? && (@state.nil? || @state[:result].value.zero?)
27
+ @state.token
67
28
  end
68
29
 
69
30
  def get_mic(token=nil)
70
31
  buffers = SecurityBuffer.new 2
71
32
  buffers.set_buffer 0, SECBUFFER_DATA, token
72
33
  buffers.set_buffer 1, SECBUFFER_TOKEN, nil, @sizes.max_signature
73
- @state[:result] = API::MakeSignature @handle, 0, buffers, 0
74
- unless @state[:result].ok?
34
+ @state.result = API::MakeSignature @handle, 0, buffers, 0
35
+ unless @state.result.complete? and (token = buffers.token(1))
75
36
  raise GeneralError, "Error creating the signature: #{result}"
76
37
  end
77
- return buffers.token(1).dup
38
+
39
+ begin return token.dup
40
+ ensure API::FreeContextBuffer token
41
+ end
78
42
  end
79
43
 
80
- def dispose()
81
- @credentials and API::FreeCredentialsHandle @credentials
82
- @handle and API::DeleteSecurityContext @handle
83
- ensure
84
- @credentials = @handle = nil
85
- end
44
+ private
45
+
46
+ def acquire_current_credentials
47
+ result = API::AcquireCredentialsHandle nil, "Kerberos", SECPKG_CRED_OUTBOUND, nil, nil, nil, nil,
48
+ creds=CredHandle.new, ts=TimeStamp.new
49
+ result.ok? or raise GeneralError, "Error acquiring credentials: #{result}"
50
+
51
+ buff = "\0\0\0\0"
52
+ result = API::QueryCredentialsAttributes creds, SECPKG_CRED_ATTR_NAMES, buff
53
+ if result.ok?
54
+ name = buff.to_ptr.ptr
55
+ begin return [creds, name.to_s.dup]
56
+ ensure API::FreeContextBuffer name
57
+ end
58
+ end
59
+ end
60
+
61
+ def release_credentials(creds)
62
+ creds.nil? or API::FreeCredentialsHandle creds
63
+ end
64
+
65
+ def import_server_name(host)
66
+ ['host/'+host, 'host/'+host]
67
+ end
68
+
69
+ def release_server_name(target)
70
+ end
71
+
72
+ def delete_context(handle)
73
+ handle.nil? or API::DeleteSecurityContext handle
74
+ end
86
75
 
87
76
  end; end; end; end; end
@@ -0,0 +1,35 @@
1
+ require File.join(File.dirname(__FILE__), 'test_helper.rb')
2
+
3
+ class GssContextTest < Test::Unit::TestCase
4
+
5
+ if defined? Net::SSH::Kerberos::GSS::Context
6
+
7
+ def setup
8
+ @gss = Net::SSH::Kerberos::GSS::Context.new
9
+ end
10
+
11
+ def teardown
12
+ @gss.dispose
13
+ end
14
+
15
+ def test_create
16
+ @gss.create ENV['USER'], Socket.gethostbyname(`hostname || echo "localhost"`.strip)[0]
17
+ assert @gss.credentials?, "Should have acquired credentials"
18
+ end
19
+
20
+ def test_init
21
+ test_create
22
+ @gss.init nil
23
+ state = @gss.send(:state)
24
+ assert ! state.handle.nil?, "Should have provided an initial context"
25
+ assert ! state.handle.handle.nil?, "Should have provided an initial context"
26
+ assert ! state.token.nil?, "Should have built an initial token"
27
+ assert state.token.length.nonzero?, "Should have built an initial token"
28
+ end
29
+
30
+ else
31
+ $stderr.puts "Skipping GSS tests on this platform: no supported GSSAPI library was loaded."
32
+ end
33
+
34
+ end
35
+
@@ -0,0 +1,97 @@
1
+ require File.join(File.dirname(__FILE__), 'test_helper.rb')
2
+
3
+ class GssTest < Test::Unit::TestCase
4
+
5
+ include Net::SSH::Kerberos::GSS
6
+
7
+ def test_acquire_cred
8
+ creds = API::GssCredRef.malloc
9
+ result = call_and_assert :gss_acquire_cred, nil, 60, nil, GSS_C_INITIATE, creds, nil, nil
10
+ assert_not_equal 0, creds.handle.to_i, "Should acquire default credentials"
11
+ begin
12
+ name = API::GssNameRef.malloc
13
+ lifetime = API::OM_uint32Ref.malloc
14
+ usage = API::GssCredUsageRef.malloc
15
+ oids = API::GssOIDSetRef.malloc
16
+ result = call_and_assert :gss_inquire_cred, creds.handle, name, nil, usage, oids
17
+ assert_not_equal 0, name.handle.to_i, "Should provide the internal name"
18
+ assert_not_equal 0, oids.oidset.count, "Should provide the supported oids"
19
+ begin
20
+ buffer = API::GssBuffer.malloc
21
+ oid = API::GssOIDRef.malloc
22
+ assert_equal GSS_C_INITIATE, usage.value, "Usage should specify GSS_C_INITIATE"
23
+ result = call_and_assert :gss_display_name, name.handle, buffer, oid
24
+ assert_not_equal 0, buffer.value.to_i, "Should provide the display name"
25
+ begin
26
+ assert_not_equal 0, oid.ptr.to_i, "Should provide the supported oid"
27
+ #$stderr.puts "credentials: #{creds.handle.to_i} #{buffer.value} (OID: #{oid.oid.length}, #{oid.oid.to_hex})"
28
+ ensure
29
+ result = API.gss_release_buffer API::OM_uint32Ref.malloc, buffer
30
+ end
31
+ ensure
32
+ minor_status = API::OM_uint32Ref.malloc
33
+ API.gss_release_name minor_status, name
34
+ API.gss_release_oid_set minor_status, oids
35
+ assert_equal 0, name.handle.to_i, "Should release the internal name"
36
+ assert_equal 0, oids.ptr.to_i, "Should release the supported oids"
37
+ end
38
+ ensure
39
+ minor_status = API::OM_uint32Ref.malloc
40
+ API.gss_release_cred minor_status, creds
41
+ end
42
+ end
43
+
44
+ def test_init_sec_context
45
+ target_name = 'host@'+Socket.gethostbyname(`hostname || echo "localhost"`.strip)[0]
46
+ buffer = API::GssBuffer.malloc
47
+ buffer.value = target_name
48
+ buffer.length = target_name.length
49
+ mech = API::GssOID.malloc
50
+ mech.elements = GSS_C_NT_HOSTBASED_SERVICE
51
+ mech.length = GSS_C_NT_HOSTBASED_SERVICE.length
52
+ target_name = API::GssNameRef.malloc
53
+ result = call_and_assert :gss_import_name, buffer, mech, target_name
54
+ assert_not_equal target_name.handle, GSS_C_NO_NAME, "Should import the name"
55
+
56
+ buffer = API::GssBuffer.malloc
57
+ result = call_and_assert :gss_display_name, target_name.handle, buffer, nil
58
+ assert_not_equal 0, buffer.value.to_i, "Should provide the display name"
59
+ #$stderr.puts "target: #{buffer.value} (OID: #{mech.length}, #{mech.to_hex})"
60
+ call_and_assert :gss_release_buffer, buffer
61
+
62
+ mech.elements = GSS_KRB5_MECH
63
+ mech.length = GSS_KRB5_MECH.length
64
+ actual_mech = API::GssOIDRef.malloc
65
+ context = API::GssContextRef.malloc
66
+ context.handle = GSS_C_NO_CONTEXT
67
+ buffer.value = nil
68
+ buffer.length = 0
69
+ result = call_and_assert :gss_init_sec_context, GSS_C_NO_CREDENTIAL, context, target_name.handle, mech,
70
+ GSS_C_DELEG_FLAG | GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG, 60,
71
+ GSS_C_NO_CHANNEL_BINDINGS, GSS_C_NO_BUFFER, actual_mech, buffer, nil, nil
72
+ assert_not_equal 0, context.handle.to_i, "Should initialize the security context"
73
+ begin
74
+ assert_equal GSS_S_CONTINUE_NEEDED, result, "Should need continued initialization of the security context"
75
+ assert buffer.length > 0, "Should output a token to send to the server"
76
+ #$stderr.puts "context: (#{buffer.length}) (OID: #{actual_mech.oid.length}, #{actual_mech.oid.to_hex})"
77
+ call_and_assert :gss_release_buffer, buffer
78
+ ensure
79
+ minor_status = API::OM_uint32Ref.malloc
80
+ API.gss_delete_sec_context minor_status, context, nil
81
+ if buffer.value.nil?
82
+ assert_equal 0, context.handle.to_i, "Should delete the security context"
83
+ end
84
+ end
85
+ end
86
+
87
+ private
88
+
89
+ def call_and_assert(sym, *args)
90
+ minor_status = API::OM_uint32Ref.malloc
91
+ result = API.send sym, minor_status, *args
92
+ assert_equal 0, (result & 0xffff0000), "#{sym} failed: 0x#{result.to_s(16)}"
93
+ assert_equal 0, minor_status.value, "#{sym} failed: minor status 0x#{minor_status.value.to_s(16)}"
94
+ result
95
+ end
96
+ end
97
+
@@ -1,7 +1,5 @@
1
1
  require File.join(File.dirname(__FILE__), 'test_helper.rb')
2
2
 
3
- include Win32::SSPI
4
-
5
3
  class SspiContextTest < Test::Unit::TestCase
6
4
 
7
5
  if defined? Net::SSH::Kerberos::SSPI::Context
@@ -21,6 +19,8 @@ if defined? Net::SSH::Kerberos::SSPI::Context
21
19
 
22
20
  else
23
21
  $stderr.puts "Skipping SSPI tests on this platform: Windows SSPI was not loaded."
22
+
23
+ def test_nothing; assert true end
24
24
  end
25
25
 
26
26
  end
@@ -1,11 +1,11 @@
1
1
  require File.join(File.dirname(__FILE__), 'test_helper.rb')
2
2
 
3
- include Win32::SSPI
4
-
5
3
  class SspiTest < Test::Unit::TestCase
6
4
 
7
5
  if defined? Net::SSH::Kerberos::SSPI::Context
8
6
 
7
+ include Win32::SSPI
8
+
9
9
  def test_query_security_package_info
10
10
  pkg_info = SecPkgInfo.new
11
11
  result = API::QuerySecurityPackageInfo "Kerberos", pkg_info
@@ -64,6 +64,8 @@ if defined? Net::SSH::Kerberos::SSPI::Context
64
64
  end
65
65
  else
66
66
  $stderr.puts "Skipping SSPI tests on this platform: Windows SSPI was not loaded."
67
+
68
+ def test_nothing; assert true end
67
69
  end
68
70
 
69
71
  end
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.2
4
+ version: 0.1.3
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-13 00:00:00 -04:00
12
+ date: 2009-10-16 00:00:00 -04:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -50,6 +50,7 @@ files:
50
50
  - VERSION.yml
51
51
  - lib/net/ssh/authentication/methods/gssapi_with_mic.rb
52
52
  - lib/net/ssh/kerberos.rb
53
+ - lib/net/ssh/kerberos/common/context.rb
53
54
  - lib/net/ssh/kerberos/constants.rb
54
55
  - lib/net/ssh/kerberos/gss.rb
55
56
  - lib/net/ssh/kerberos/gss/api.rb
@@ -60,6 +61,8 @@ files:
60
61
  - lib/net/ssh/kerberos/sspi.rb
61
62
  - lib/net/ssh/kerberos/sspi/api.rb
62
63
  - lib/net/ssh/kerberos/sspi/context.rb
64
+ - test/gss_context_test.rb
65
+ - test/gss_test.rb
63
66
  - test/net_ssh_kerberos_test.rb
64
67
  - test/sspi_context_test.rb
65
68
  - test/sspi_test.rb
@@ -93,6 +96,8 @@ signing_key:
93
96
  specification_version: 3
94
97
  summary: Add Kerberos support to Net::SSH
95
98
  test_files:
99
+ - test/gss_context_test.rb
100
+ - test/gss_test.rb
96
101
  - test/net_ssh_kerberos_test.rb
97
102
  - test/sspi_context_test.rb
98
103
  - test/sspi_test.rb