winrm-s 0.1.0.rc.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ MDRmZmUzNTQ4MDI3ZDc4YjY4MDcwMTk4NTY4ZWY3MmUzYTAwY2M5Nw==
5
+ data.tar.gz: !binary |-
6
+ YzgwZjhlN2UxNTZmNThlOGNjMWVkNDZhZjFhOGZjMTg5NzI3ODhmZQ==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ NzAxNzMwNDE5ODIwZDQ1ZWVhMWI2MTE3MjZmNjNhOWNmYjE5MTgwNGI2OWQx
10
+ MzY0MjlhN2JlNDVjMDY3YzFlNTdlMjAzOWQ0Mzg0OTY0ZGMyZmE2NTg1ODJh
11
+ MmUyNmI0M2EyMzZkNTlhNjIzMWU5ZmQ0ZDVmNjI0NmU1ZWYxOTA=
12
+ data.tar.gz: !binary |-
13
+ MGM5NmI4ZTdhZjVkYzk2OTFhYWNiMmNlMzMwYjkyN2JhZmY2MDcwNjM3MmFm
14
+ MGU2NWU2Y2MzOWZjNWI1M2M2ZWFhMzFhNzYyN2Q1M2JkNTkzMGMzMmFkZWE0
15
+ OTUxY2M3ZTE5YjllZjhkNjhkYWQ1ODY5ZjgwN2UyNzU2MWI1NTA=
@@ -0,0 +1,27 @@
1
+ .autotest
2
+ coverage
3
+ .DS_Store
4
+ pkg
5
+ */tags
6
+ *~
7
+
8
+ # you should check in your Gemfile.lock in applications, and not in gems
9
+ Gemfile.lock
10
+ Gemfile.local
11
+
12
+ # Do not check in the .bundle directory, or any of the files inside it. Those files are specific to each particular machine, and are used to persist installation options between runs of the bundle install command.
13
+ .bundle
14
+
15
+ # ignore some common Bundler 'binstubs' directory names
16
+ # http://gembundler.com/man/bundle-exec.1.html
17
+ b/
18
+ binstubs/
19
+
20
+ # RVM and RBENV ruby version files
21
+ .rbenv-version
22
+ .rvmrc
23
+
24
+ # Documentation
25
+ _site/*
26
+ .yardoc/
27
+ doc/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ -fdocumentation
@@ -0,0 +1,8 @@
1
+ rvm:
2
+ # - 1.8.7
3
+ - 1.9.2
4
+ - 1.9.3
5
+ - 2.0.0
6
+ - 2.1.0
7
+
8
+ script: bundle exec rake spec
@@ -0,0 +1,11 @@
1
+ # winrm-s Change Log
2
+
3
+ ## Unreleased
4
+ * Initial implementation
5
+
6
+ Last Release: none
7
+ -------------------
8
+
9
+
10
+
11
+
@@ -0,0 +1,5 @@
1
+ # Contributing to winrm-s
2
+
3
+ We are glad you want to contribute to winrm-s. Please see contribution guidelines for
4
+ [Chef](http://wiki.opscode.com/display/chef/How+to+Contribute) for information on contributing to this project.
5
+
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
3
+
4
+ group :test, :development do
5
+ gem "rspec"
6
+ gem 'rake'
7
+ gem 'nokogiri', '~> 1.6.2'
8
+ end
data/LICENSE ADDED
@@ -0,0 +1,201 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "[]"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright [yyyy] [name of copyright owner]
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
@@ -0,0 +1,69 @@
1
+ winrm-s
2
+ =======
3
+
4
+ `winrm-s` extends the functionality of the
5
+ [WinRM gem](http://rubygems.org/gems/winrm) to support the Microsoft
6
+ [Negotiate protocol](http://msdn.microsoft.com/en-us/library/windows/desktop/aa378748(v=vs.85).aspx)
7
+ when authenticating to a remote [WinRM](http://msdn.microsoft.com/en-us/library/aa384426(v=vs.85).aspx) endpoint from a Windows system.
8
+
9
+ This extended functionality is **only** supported when running on Microsoft
10
+ Windows. This gem can still be used on other operating systems just like the
11
+ `WinRM` gem, but the extended capabilities will not be available.
12
+
13
+ Installation
14
+ ------------
15
+
16
+ To install it, run:
17
+
18
+ gem install winrm-s
19
+
20
+ Usage
21
+ -----
22
+
23
+ `winrm-s` provides the same interface as the `winrm` gem -- see `winrm`
24
+ [documentation](https://github.com/WinRb/WinRM/blob/master/README.md) for `winrm-s` usage.
25
+
26
+ * To use it, simply require `winrm` or `winrm-s`, depending on whether your code
27
+ is running on Windows. The extended negotiate protocol is only available if
28
+ you include `winrm-s`, which will only work on Windows.
29
+ * When you use WinRM::WinRMWebService.new, be sure to specify the
30
+ `:sspinegotiate` parameter, along with a user name in the form `domain_name\user_name`
31
+ for the user name in order to make use of negotiate protocol. If the user
32
+ account is local to the remote system, you can use `.` for the domain. The
33
+ example further on demonstrates the negotiate use case.
34
+ * All other use cases enabled by the `winrm` gem are also supported.
35
+
36
+ Example
37
+ -------
38
+ Note the argument value of `:sspinegotiate` for transport option, and the
39
+ explicit specification of a domain name, in this case `.`, in the user name:
40
+ ```ruby
41
+ if RUBY_PLATFORM =~ /mswin|mingw32|windows/
42
+ require 'winrm-s' # only works on Windows, otherwise use require 'winrm'
43
+ endpoint = http://mywinrmhost:5985/wsman
44
+ winrm = WinRM::WinRMWebService.new(endpoint, :sspinegotiate, :user => ".\administrator", :pass => "adminpasswd")
45
+ winrm.cmd('ipconfig /all') do |stdout, stderr|
46
+ STDOUT.print stdout
47
+ STDERR.print stderr
48
+ end
49
+ end
50
+ ```
51
+
52
+ License
53
+ -------
54
+
55
+ Copyright:: Copyright (c) 2014 Chef Software, Inc.
56
+ License:: Apache License, Version 2.0
57
+
58
+ Licensed under the Apache License, Version 2.0 (the "License");
59
+ you may not use this file except in compliance with the License.
60
+ You may obtain a copy of the License at
61
+
62
+ http://www.apache.org/licenses/LICENSE-2.0
63
+
64
+ Unless required by applicable law or agreed to in writing, software
65
+ distributed under the License is distributed on an "AS IS" BASIS,
66
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
67
+ See the License for the specific language governing permissions and
68
+ limitations under the License.
69
+
@@ -0,0 +1 @@
1
+ require 'bundler/gem_tasks'
@@ -0,0 +1,30 @@
1
+ #
2
+ # Author:: Kaustubh Deorukhkar (<kaustubh@clogeny.com>)>
3
+ # Copyright:: Copyright (c) 2014 Chef Software, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ require 'winrm'
20
+
21
+ def windows?
22
+ !!(RUBY_PLATFORM =~ /mswin|mingw|windows/)
23
+ end
24
+
25
+ # Patch only on windows
26
+ if windows?
27
+ require 'winrm/winrm_service_patch'
28
+ else
29
+ raise "ERROR: winrm-s extensions to the winrm gem for the negotiate protocol are only supported on Windows. Require 'winrm' and not 'winrm-s' on non-Windows platforms."
30
+ end
@@ -0,0 +1,22 @@
1
+ #
2
+ # Author:: Kaustubh Deorukhkar (<kaustubh@clogeny.com>)
3
+ # Copyright:: Copyright (c) 2014 Chef Software, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ module WinrmS
20
+ VERSION = "0.1.0.rc.0"
21
+ MAJOR, MINOR, TINY = VERSION.split('.')
22
+ end
@@ -0,0 +1,20 @@
1
+
2
+ module PatchAssertions
3
+
4
+ def self.assert_major_version(library_name, expected_major, override_var_name)
5
+ supported_major_ver = ENV[override_var_name] || expected_major
6
+ loaded_ver = Gem.loaded_specs[library_name].version
7
+ loaded_major_ver = loaded_ver.to_s.match(/(^\d+\.\d+)\.(.*)$/)[1]
8
+ if loaded_major_ver.to_s != supported_major_ver.to_s
9
+ puts "Unsupported version of #{library_name}. The supported major version of library is #{library_name} version #{expected_major}. This code path monkey patches few methods in #{library_name} to support additional features. If you are aware of the impact of using #{loaded_ver}, this can be enabled by setting #{override_var_name} to the major version #{loaded_major_ver}"
10
+ exit 1
11
+ end
12
+ end
13
+
14
+ def self.assert_arity_of_patched_method(klass, method_name, expected_arity)
15
+ if klass.instance_method(method_name).arity != expected_arity
16
+ puts "Cannot patch method #{klass}::#{method_name} since your latest gem seems to have different method definition that cannot be safely patched. Please use the supported version of patched gem."
17
+ exit 1
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,171 @@
1
+ #
2
+ # Author:: Kaustubh Deorukhkar (<kaustubh@clogeny.com>)
3
+ # Copyright:: Copyright (c) 2014 Chef Software, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ require 'httpclient/auth'
20
+
21
+ require 'winrm/helpers/assert_patch'
22
+
23
+ def validate_patch
24
+ # The code below patches the httpclient library to add support
25
+ # for encrypt/decrypt as described below.
26
+ # Add few restriction to make sure the patched methods are still
27
+ # available, but still give a way to consciously use later versions
28
+ PatchAssertions.assert_major_version("httpclient", 2.4, "USE_HTTPCLIENT_MAJOR")
29
+ PatchAssertions.assert_arity_of_patched_method(HTTPClient::WWWAuth, "filter_request", 1)
30
+ PatchAssertions.assert_arity_of_patched_method(HTTPClient::WWWAuth, "filter_response", 2)
31
+ PatchAssertions.assert_arity_of_patched_method(HTTPClient::SSPINegotiateAuth, "set", -1)
32
+ PatchAssertions.assert_arity_of_patched_method(HTTPClient::SSPINegotiateAuth, "get", 1)
33
+ end
34
+
35
+ # Perform the patch validations
36
+ validate_patch
37
+
38
+ # Overrides the HTTPClient::WWWAuth code to add support for encryption/decryption
39
+ # of data sent during the NTLM auth over negotiate.
40
+
41
+ # Also Overrides HTTPClient::SSPINegotiateAuth to remember user credentials, original
42
+ # library code relies on the current login user credentials on the client machine.
43
+
44
+ # Below code helps ruby client to perform auth using the credentials provided to
45
+ # ruby client, and also enhances to use encrypted channel.
46
+
47
+ class HTTPClient
48
+
49
+ class WWWAuth
50
+
51
+ # Filter API implementation. Traps HTTP request and insert
52
+ # 'Authorization' header if needed.
53
+ def filter_request(req)
54
+ @authenticator.each do |auth|
55
+ next unless auth.set? # hasn't be set, don't use it
56
+ if cred = auth.get(req)
57
+ auth.encrypt_payload(req) if auth.respond_to?(:encrypt_payload)
58
+ req.header.set('Authorization', auth.scheme + " " + cred)
59
+ return
60
+ end
61
+ end
62
+ end
63
+
64
+ # Filter API implementation. Traps HTTP response and parses
65
+ # 'WWW-Authenticate' header.
66
+ #
67
+ # This remembers the challenges for all authentication methods
68
+ # available to the client. On the subsequent retry of the request,
69
+ # filter_request will select the strongest method.
70
+ def filter_response(req, res)
71
+ command = nil
72
+ if res.status == HTTP::Status::UNAUTHORIZED
73
+ if challenge = parse_authentication_header(res, 'www-authenticate')
74
+ uri = req.header.request_uri
75
+ challenge.each do |scheme, param_str|
76
+ @authenticator.each do |auth|
77
+ next unless auth.set? # hasn't be set, don't use it
78
+ if scheme.downcase == auth.scheme.downcase
79
+ challengeable = auth.challenge(uri, param_str)
80
+ command = :retry if challengeable
81
+ end
82
+ end
83
+ end
84
+ # ignore unknown authentication scheme
85
+ end
86
+ elsif res.status == HTTP::Status::OK
87
+ decrypted_content = res.content
88
+ @authenticator.each do |auth|
89
+ next unless auth.set? # hasn't be set, don't use it
90
+ decrypted_content = auth.decrypt_payload(res.content) if auth.respond_to?(:encrypted_channel?) and auth.encrypted_channel?
91
+ end
92
+ # update with decrypted content
93
+ res.content.replace(decrypted_content) if res.content and !res.content.empty?
94
+ end
95
+ command
96
+ end
97
+ end
98
+
99
+ class SSPINegotiateAuth
100
+ # Override to remember creds
101
+ # Set authentication credential.
102
+ def set(uri, user, passwd)
103
+ # Check if user has domain specified in it.
104
+ if user
105
+ creds = user.split("\\")
106
+ creds.length.eql?(2) ? (@domain,@user = creds) : @user = creds[0]
107
+ end
108
+ @passwd = passwd
109
+ end
110
+
111
+ # Response handler: returns credential.
112
+ # See win32/sspi for negotiation state transition.
113
+ def get(req)
114
+ return nil unless SSPIEnabled || GSSAPIEnabled
115
+ target_uri = req.header.request_uri
116
+ domain_uri, param = @challenge.find { |uri, v|
117
+ Util.uri_part_of(target_uri, uri)
118
+ }
119
+
120
+ return nil unless param
121
+ state = param[:state]
122
+ authenticator = param[:authenticator]
123
+ authphrase = param[:authphrase]
124
+ case state
125
+ when :init
126
+ if SSPIEnabled
127
+ # Over-ride ruby win32 sspi to support encrypt/decrypt
128
+ require 'winrm/win32/sspi'
129
+ authenticator = param[:authenticator] = Win32::SSPI::NegotiateAuth.new(@user, @domain, @passwd)
130
+ @authenticator = authenticator # **** Hacky remember as we need this for encrypt/decrypt
131
+ return authenticator.get_initial_token
132
+ else # use GSSAPI
133
+ authenticator = param[:authenticator] = GSSAPI::Simple.new(domain_uri.host, 'HTTP')
134
+ # Base64 encode the context token
135
+ return [authenticator.init_context].pack('m').gsub(/\n/,'')
136
+ end
137
+ when :response
138
+ @challenge.delete(domain_uri)
139
+ if SSPIEnabled
140
+ return authenticator.complete_authentication(authphrase)
141
+ else # use GSSAPI
142
+ return authenticator.init_context(authphrase.unpack('m').pop)
143
+ end
144
+ end
145
+ nil
146
+ end
147
+
148
+ def encrypted_channel?
149
+ @encrypted_channel
150
+ end
151
+
152
+ def encrypt_payload(req)
153
+ if SSPIEnabled
154
+ body = @authenticator.encrypt_payload(req.body)
155
+ req.http_body = HTTP::Message::Body.new
156
+ req.http_body.init_request(body)
157
+ req.http_header.body_size = body.length if body
158
+ # if body is encrypted update the header
159
+ if body.include? "HTTP-SPNEGO-session-encrypted"
160
+ @encrypted_channel = true
161
+ req.header.set('Content-Type', "multipart/encrypted;protocol=\"application/HTTP-SPNEGO-session-encrypted\";boundary=\"Encrypted Boundary\"")
162
+ end
163
+ end
164
+ end
165
+
166
+ def decrypt_payload(body)
167
+ body = @authenticator.decrypt_payload(body) if SSPIEnabled
168
+ body
169
+ end
170
+ end
171
+ end
@@ -0,0 +1,35 @@
1
+ #
2
+ # Author:: Kaustubh Deorukhkar (<kaustubh@clogeny.com>)
3
+ # Copyright:: Copyright (c) 2014 Chef Software, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ module WinRM
20
+ module HTTP
21
+
22
+ class HttpSSPINegotiate < HttpTransport
23
+ def initialize(endpoint, user, pass, opts)
24
+ # Override the relevant functionality in httpclient to make sspi work.
25
+ require 'winrm/http/auth'
26
+ super(endpoint)
27
+ @httpcli.set_auth(nil, user, pass)
28
+ # Remove non-sspi auths
29
+ auths = @httpcli.www_auth.instance_variable_get('@authenticator')
30
+ auths.delete_if {|i| not i.is_a?(HTTPClient::SSPINegotiateAuth)}
31
+ end
32
+ end
33
+
34
+ end
35
+ end # WinRM
@@ -0,0 +1,256 @@
1
+
2
+ require 'winrm/helpers/assert_patch'
3
+
4
+ def validate_patch
5
+ # The code below patches the Win32::SSPI module from ruby core to add support
6
+ # for encrypt/decrypt as described below.
7
+ # Add few restrictions to make sure the patched methods are still
8
+ # available, but still give a way to consciously use later versions
9
+ PatchAssertions.assert_arity_of_patched_method(Win32::SSPI::NegotiateAuth, "initialize", -1)
10
+ PatchAssertions.assert_arity_of_patched_method(Win32::SSPI::NegotiateAuth, "complete_authentication", 1)
11
+ PatchAssertions.assert_arity_of_patched_method(Win32::SSPI::NegotiateAuth, "get_credentials", 0)
12
+ end
13
+
14
+ # Perform the patch validations
15
+ validate_patch
16
+
17
+ # Overrides and enhances the ruby core win32 sspi module to add support to
18
+ # encrypt/decrypt data to be sent over channel, example using SSP Negotiate auth
19
+
20
+ module Win32
21
+ module SSPI
22
+ # QueryContextAttributes attributes flags
23
+ SECPKG_ATTR_SIZES = 0x00000000
24
+
25
+ module API
26
+ QueryContextAttributes = Win32API.new("secur32", "QueryContextAttributes", 'pLp', 'L')
27
+ EncryptMessage = Win32API.new("secur32", "EncryptMessage", 'pLpL', 'L')
28
+ DecryptMessage = Win32API.new("secur32", "DecryptMessage", 'ppLp', 'L')
29
+ end
30
+
31
+ class SecPkgContext_Sizes
32
+ attr_accessor :cbMaxToken, :cbMaxSignature, :cbBlockSize, :cbSecurityTrailer
33
+
34
+ def initialize
35
+ @cbMaxToken = @cbMaxSignature = @cbBlockSize = @cbSecurityTrailer = 0
36
+ end
37
+
38
+ def cbMaxToken
39
+ @cbMaxToken = @struct.unpack("LLLL")[0] if @struct
40
+ end
41
+
42
+ def cbMaxSignature
43
+ @cbMaxSignature = @struct.unpack("LLLL")[1] if @struct
44
+ end
45
+
46
+ def cbBlockSize
47
+ @cbBlockSize = @struct.unpack("LLLL")[2] if @struct
48
+ end
49
+
50
+ def cbSecurityTrailer
51
+ @cbSecurityTrailer = @struct.unpack("LLLL")[3] if @struct
52
+ end
53
+
54
+ def to_p
55
+ @struct ||= [@cbMaxToken, @cbMaxSignature, @cbBlockSize, @cbSecurityTrailer].pack("LLLL")
56
+ end
57
+ end
58
+
59
+ # SecurityBuffer for data to be encrypted
60
+ class EncryptedSecurityBuffer
61
+
62
+ SECBUFFER_DATA = 0x1 # Security buffer data
63
+ SECBUFFER_TOKEN = 0x2 # Security token
64
+ SECBUFFER_VERSION = 0
65
+
66
+ def initialize(data_buffer, sizes)
67
+ @original_msg_len = data_buffer.length
68
+ @cbSecurityTrailer = sizes.cbSecurityTrailer
69
+ @data_buffer = data_buffer
70
+ @security_trailer = "\0" * sizes.cbSecurityTrailer
71
+ end
72
+
73
+ def to_p
74
+ # Assumption is that when to_p is called we are going to get a packed structure. Therefore,
75
+ # set @unpacked back to nil so we know to unpack when accessors are next accessed.
76
+ @unpacked = nil
77
+ # Assignment of inner structure to variable is very important here. Without it,
78
+ # will not be able to unpack changes to the structure. Alternative, nested unpacks,
79
+ # does not work (i.e. @struct.unpack("LLP12")[2].unpack("LLP12") results in "no associated pointer")
80
+ @sec_buffer = [@original_msg_len, SECBUFFER_DATA, @data_buffer, @cbSecurityTrailer, SECBUFFER_TOKEN, @security_trailer].pack("LLPLLP")
81
+ @struct ||= [SECBUFFER_VERSION, 2, @sec_buffer].pack("LLP")
82
+ end
83
+
84
+ def buffer
85
+ unpack
86
+ @buffer
87
+ end
88
+
89
+ private
90
+
91
+ # Unpacks the SecurityBufferDesc structure into member variables. We
92
+ # only want to do this once per struct, so the struct is deleted
93
+ # after unpacking.
94
+ def unpack
95
+ if ! @unpacked && @sec_buffer && @struct
96
+ dataBufferSize, dType, dataBuffer, tokenBufferSize, tType, tokenBuffer = @sec_buffer.unpack("LLPLLP")
97
+ dataBufferSize, dType, dataBuffer, tokenBufferSize, tType, tokenBuffer = @sec_buffer.unpack("LLP#{dataBufferSize}LLP#{tokenBufferSize}")
98
+ # Form the buffer stream as required by server
99
+ @buffer = [tokenBufferSize].pack("L")
100
+ @buffer << tokenBuffer << dataBuffer
101
+ @struct = nil
102
+ @sec_buffer = nil
103
+ @unpacked = true
104
+ end
105
+ end
106
+ end
107
+
108
+ class DecryptedSecurityBuffer
109
+
110
+ SECBUFFER_DATA = 0x1 # Security buffer data
111
+ SECBUFFER_TOKEN = 0x2 # Security token
112
+ SECBUFFER_VERSION = 0
113
+
114
+ def initialize(buffer)
115
+ # unpack to extract the msg and token
116
+ token_size, token_buffer, enc_buffer = buffer.unpack("L")
117
+ @original_msg_len = buffer.length - token_size - 4
118
+ @cbSecurityTrailer, @security_trailer, @data_buffer = buffer.unpack("La#{token_size}a#{@original_msg_len}")
119
+ end
120
+
121
+ def to_p
122
+ # Assumption is that when to_p is called we are going to get a packed structure. Therefore,
123
+ # set @unpacked back to nil so we know to unpack when accessors are next accessed.
124
+ @unpacked = nil
125
+ # Assignment of inner structure to variable is very important here. Without it,
126
+ # will not be able to unpack changes to the structure. Alternative, nested unpacks,
127
+ # does not work (i.e. @struct.unpack("LLP12")[2].unpack("LLP12") results in "no associated pointer")
128
+ @sec_buffer = [@original_msg_len, SECBUFFER_DATA, @data_buffer, @cbSecurityTrailer, SECBUFFER_TOKEN, @security_trailer].pack("LLPLLP")
129
+ @struct ||= [SECBUFFER_VERSION, 2, @sec_buffer].pack("LLP")
130
+ end
131
+
132
+ def buffer
133
+ unpack
134
+ @buffer
135
+ end
136
+
137
+ private
138
+
139
+ # Unpacks the SecurityBufferDesc structure into member variables. We
140
+ # only want to do this once per struct, so the struct is deleted
141
+ # after unpacking.
142
+ def unpack
143
+ if ! @unpacked && @sec_buffer && @struct
144
+ dataBufferSize, dType, dataBuffer, tokenBufferSize, tType, tokenBuffer = @sec_buffer.unpack("LLPLLP")
145
+ dataBufferSize, dType, dataBuffer, tokenBufferSize, tType, tokenBuffer = @sec_buffer.unpack("LLP#{dataBufferSize}LLP#{tokenBufferSize}")
146
+ @buffer = dataBuffer
147
+ @struct = nil
148
+ @sec_buffer = nil
149
+ @unpacked = true
150
+ end
151
+ end
152
+ end
153
+
154
+ class NegotiateAuth
155
+ # Override to remember password
156
+ # Creates a new instance ready for authentication as the given user in the given domain.
157
+ # Defaults to current user and domain as defined by ENV["USERDOMAIN"] and ENV["USERNAME"] if
158
+ # no arguments are supplied.
159
+ def initialize(user = nil, domain = nil, password = nil)
160
+ if user.nil? && domain.nil? && ENV["USERNAME"].nil? && ENV["USERDOMAIN"].nil?
161
+ raise "A username or domain must be supplied since they cannot be retrieved from the environment"
162
+ end
163
+ @user = user || ENV["USERNAME"]
164
+ @domain = domain || ENV["USERDOMAIN"]
165
+ @password = password
166
+ end
167
+
168
+ # Takes a token and gets the next token in the Negotiate authentication chain. Token can be Base64 encoded or not.
169
+ # The token can include the "Negotiate" header and it will be stripped.
170
+ # Does not indicate if SEC_I_CONTINUE or SEC_E_OK was returned.
171
+ # Token returned is Base64 encoded w/ all new lines removed.
172
+ def complete_authentication(token)
173
+ raise "This object is no longer usable because its resources have been freed." if @cleaned_up
174
+
175
+ # Nil token OK, just set it to empty string
176
+ token = "" if token.nil?
177
+
178
+ if token.include? "Negotiate"
179
+ # If the Negotiate prefix is passed in, assume we are seeing "Negotiate <token>" and get the token.
180
+ token = token.split(" ").last
181
+ end
182
+
183
+ if token.include? B64_TOKEN_PREFIX
184
+ # indicates base64 encoded token
185
+ token = token.strip.unpack("m")[0]
186
+ end
187
+
188
+ outputBuffer = SecurityBuffer.new
189
+ result = SSPIResult.new(API::InitializeSecurityContext.call(@credentials.to_p, @context.to_p, nil,
190
+ REQUEST_FLAGS, 0, SECURITY_NETWORK_DREP, SecurityBuffer.new(token).to_p, 0,
191
+ @context.to_p,
192
+ outputBuffer.to_p, @contextAttributes, TimeStamp.new.to_p))
193
+
194
+ if result.ok? then
195
+ @auth_successful = true
196
+ return encode_token(outputBuffer.token)
197
+ else
198
+ raise "Error: #{result.to_s}"
199
+ end
200
+ ensure
201
+ # need to make sure we don't clean up if we've already cleaned up.
202
+ # XXX - clean up later since encrypt/decrypt needs this
203
+ # clean_up unless @cleaned_up
204
+ end
205
+
206
+ def encrypt_payload(body)
207
+ if @auth_successful
208
+ # Approach - http://msdn.microsoft.com/en-us/magazine/cc301890.aspx
209
+ sizes = SecPkgContext_Sizes.new
210
+ result = SSPIResult.new(API::QueryContextAttributes.call(@context.to_p, SECPKG_ATTR_SIZES, sizes.to_p))
211
+
212
+ outputBuffer = EncryptedSecurityBuffer.new(body, sizes)
213
+ result = SSPIResult.new(API::EncryptMessage.call(@context.to_p, 0, outputBuffer.to_p, 0 ))
214
+ encrypted_msg = outputBuffer.buffer
215
+
216
+ body = <<-EOF
217
+ --Encrypted Boundary\r
218
+ Content-Type: application/HTTP-SPNEGO-session-encrypted\r
219
+ OriginalContent: type=application/soap+xml;charset=UTF-8;Length=#{encrypted_msg.length - sizes.cbSecurityTrailer - 4}\r
220
+ --Encrypted Boundary\r
221
+ Content-Type: application/octet-stream\r
222
+ #{encrypted_msg}--Encrypted Boundary\r
223
+ EOF
224
+ end
225
+ body
226
+ end
227
+
228
+ def decrypt_payload(body)
229
+ if @auth_successful
230
+
231
+ matched_data = /--Encrypted Boundary\s+Content-Type:\s+application\/HTTP-SPNEGO-session-encrypted\s+OriginalContent:\s+type=\S+Length=(\d+)\s+--Encrypted Boundary\s+Content-Type:\s+application\/octet-stream\s+([\S\s]+)--Encrypted Boundary/.match(body)
232
+ raise "Error: Unencrypted communication not supported. Please check winrm configuration winrm/config/service AllowUnencrypted flag." if matched_data.nil?
233
+
234
+ encrypted_msg = matched_data[2]
235
+
236
+ outputBuffer = DecryptedSecurityBuffer.new(encrypted_msg)
237
+ result = SSPIResult.new(API::DecryptMessage.call(@context.to_p, outputBuffer.to_p, 0, 0 ))
238
+ body = outputBuffer.buffer
239
+ end
240
+ body
241
+ end
242
+
243
+ private
244
+ # ** Override to add password support
245
+ # Gets credentials based on user, domain or both. If both are nil, an error occurs
246
+ def get_credentials
247
+ @credentials = CredHandle.new
248
+ ts = TimeStamp.new
249
+ @identity = Identity.new @user, @domain, @password
250
+ result = SSPIResult.new(API::AcquireCredentialsHandle.call(nil, "Negotiate", SECPKG_CRED_OUTBOUND, nil, @identity.to_p,
251
+ nil, nil, @credentials.to_p, ts.to_p))
252
+ raise "Error acquire credentials: #{result}" unless result.ok?
253
+ end
254
+ end
255
+ end
256
+ end
@@ -0,0 +1,34 @@
1
+
2
+ require 'winrm/http/transport_patch'
3
+
4
+ module WinRM
5
+ class WinRMWebService
6
+
7
+ # Override winrm to support sspinegotiate option.
8
+
9
+ # @param [String,URI] endpoint the WinRM webservice endpoint
10
+ # @param [Symbol] transport either :kerberos(default)/:ssl/:plaintext
11
+ # @param [Hash] opts Misc opts for the various transports.
12
+ # @see WinRM::HTTP::HttpTransport
13
+ # @see WinRM::HTTP::HttpGSSAPI
14
+ # @see WinRM::HTTP::HttpSSL
15
+ def initialize(endpoint, transport = :kerberos, opts = {})
16
+ @endpoint = endpoint
17
+ @timeout = DEFAULT_TIMEOUT
18
+ @max_env_sz = DEFAULT_MAX_ENV_SIZE
19
+ @locale = DEFAULT_LOCALE
20
+ case transport
21
+ when :kerberos
22
+ require 'gssapi'
23
+ # TODO: check fo keys and throw error if missing
24
+ @xfer = HTTP::HttpGSSAPI.new(endpoint, opts[:realm], opts[:service], opts[:keytab], opts)
25
+ when :plaintext
26
+ @xfer = HTTP::HttpPlaintext.new(endpoint, opts[:user], opts[:pass], opts)
27
+ when :sspinegotiate
28
+ @xfer = HTTP::HttpSSPINegotiate.new(endpoint, opts[:user], opts[:pass], opts)
29
+ when :ssl
30
+ @xfer = HTTP::HttpSSL.new(endpoint, opts[:user], opts[:pass], opts[:ca_trust_path], opts)
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,65 @@
1
+ require 'spec_helper'
2
+
3
+ def assert_prerequisites
4
+ if windows?
5
+ require 'winrm-s'
6
+ ["test_winrm_endpoint", "test_winrm_user", "test_winrm_pass"].each do |env_var|
7
+ raise "\n\nError: Please set the environment variable: #{env_var}\n\n" if ENV[env_var].nil?
8
+ end
9
+ end
10
+ end
11
+
12
+
13
+ describe "Test sspinegotiate with encrypt/decrypt via WinRM", :windows_and_func_spec_enabled do
14
+ before(:all) do
15
+ assert_prerequisites
16
+ # Remember the user setting.
17
+ winrm_cfg = %x{winrm get winrm/config/service -format:xml}
18
+ doc = Nokogiri::XML(winrm_cfg)
19
+ @original_allowunencrypted_val = doc.at_css("cfg|Service cfg|AllowUnencrypted").text.to_s
20
+ end
21
+
22
+ before do
23
+ %x{winrm set winrm/config/service @{AllowUnencrypted="false"}}
24
+ @winrm = WinRM::WinRMWebService.new(ENV["test_winrm_endpoint"], :sspinegotiate, :user => ENV["test_winrm_user"], :pass => ENV["test_winrm_pass"])
25
+ end
26
+
27
+ after(:all) do
28
+ %x{winrm set winrm/config/service @{AllowUnencrypted="#{@original_allowunencrypted_val}"}}
29
+ end
30
+
31
+ it 'should run a CMD command string' do
32
+ output = @winrm.run_cmd('ipconfig /all')
33
+ expect(output[:exitcode]).to be_zero
34
+ expect(output[:data]).not_to be_empty
35
+ end
36
+
37
+ it 'should run a CMD command with proper arguments' do
38
+ output = @winrm.run_cmd('ipconfig', %w{/all})
39
+ expect(output[:exitcode]).to be_zero
40
+ expect(output[:data]).not_to be_empty
41
+ end
42
+
43
+ it 'should run a CMD command with block' do
44
+ outvar = ''
45
+ @winrm.run_cmd('ipconfig', %w{/all}) do |stdout, stderr|
46
+ outvar << stdout
47
+ end
48
+ expect(outvar).to match(/Windows IP Configuration/)
49
+ end
50
+
51
+ describe "Negative test:" do
52
+ before do
53
+ %x{winrm set winrm/config/service @{AllowUnencrypted="true"}}
54
+ end
55
+ after do
56
+ %x{winrm set winrm/config/service @{AllowUnencrypted="false"}}
57
+ end
58
+
59
+ describe "when AllowUnencrypted is set to true" do
60
+ it "should raise an exception" do
61
+ expect{@winrm.run_cmd('ipconfig')}.to raise_exception
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,21 @@
1
+ $:.unshift File.expand_path('../../lib', __FILE__)
2
+
3
+ require 'nokogiri'
4
+
5
+ def windows?
6
+ !!(RUBY_PLATFORM =~ /mswin|mingw|windows/)
7
+ end
8
+
9
+ def unix?
10
+ !windows?
11
+ end
12
+
13
+ def windows_and_func_spec_enabled?
14
+ windows? and ENV["enable_winrms_func_spec"]
15
+ end
16
+
17
+ RSpec.configure do |config|
18
+ config.filter_run_excluding :windows_only => true unless windows?
19
+ config.filter_run_excluding :windows_and_func_spec_enabled => true unless windows_and_func_spec_enabled?
20
+ config.filter_run_excluding :unix_only => true unless unix?
21
+ end
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+
3
+
4
+ describe "Test if patch is applied on Platform" do
5
+
6
+ describe 'Windows is succesfully patched for transport sspinegotiate', :windows_only do
7
+ before do
8
+ require 'winrm-s'
9
+ @winrm = WinRM::WinRMWebService.new("http://mywinrmhost:5985/wsman", :sspinegotiate, :user => "test_winrm_user", :pass => "test_winrm_pass")
10
+ end
11
+
12
+ it 'HTTP::HttpSSPINegotiate class should exist' do
13
+ expect{WinRM::HTTP::HttpSSPINegotiate}.not_to raise_exception
14
+ end
15
+
16
+ it 'should patch httpclient to contain encrypt/decrypt methods' do
17
+ expect(HTTPClient::SSPINegotiateAuth.new).to respond_to(:encrypt_payload)
18
+ expect(HTTPClient::SSPINegotiateAuth.new).to respond_to(:decrypt_payload)
19
+ end
20
+
21
+ end
22
+
23
+ describe 'Winrm cannot be patched for unix', :unix_only do
24
+ it 'require winrm-s should raise exception' do
25
+ expect{require 'winrm-s'}.to raise_exception
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,25 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "winrm-s/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "winrm-s"
7
+ s.version = WinrmS::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.has_rdoc = true
10
+ s.extra_rdoc_files = ["README.md", "LICENSE" ]
11
+ s.authors = ["Kaustubh Deorukhkar"]
12
+ s.email = ["dev@getchef.com", "kaustubh@clogeny.com"]
13
+ s.homepage = "https://github.com/opscode/winrm-s"
14
+ s.summary = %q{Gem that extends the functionality of the WinRM gem to support the Microsoft Negotiate protocol when authenticating to a remote WinRM endpoint from a Windows system}
15
+ s.description = s.summary
16
+
17
+ s.add_dependency "winrm", "~> 1.1.3"
18
+
19
+ %w(rspec-core rspec-expectations rspec-mocks rspec_junit_formatter).each { |gem| s.add_development_dependency gem }
20
+
21
+ s.files = `git ls-files`.split("\n")
22
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
23
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
24
+ s.require_paths = ["lib"]
25
+ end
metadata ADDED
@@ -0,0 +1,144 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: winrm-s
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0.rc.0
5
+ platform: ruby
6
+ authors:
7
+ - Kaustubh Deorukhkar
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-06-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: winrm
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: 1.1.3
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: 1.1.3
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec-core
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ! '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec-expectations
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ! '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec-mocks
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ! '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec_junit_formatter
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ! '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ! '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: Gem that extends the functionality of the WinRM gem to support the Microsoft
84
+ Negotiate protocol when authenticating to a remote WinRM endpoint from a Windows
85
+ system
86
+ email:
87
+ - dev@getchef.com
88
+ - kaustubh@clogeny.com
89
+ executables: []
90
+ extensions: []
91
+ extra_rdoc_files:
92
+ - README.md
93
+ - LICENSE
94
+ files:
95
+ - .gitignore
96
+ - .rspec
97
+ - .travis.yml
98
+ - CHANGELOG.md
99
+ - CONTRIBUTING.md
100
+ - Gemfile
101
+ - LICENSE
102
+ - README.md
103
+ - Rakefile
104
+ - lib/winrm-s.rb
105
+ - lib/winrm-s/version.rb
106
+ - lib/winrm/helpers/assert_patch.rb
107
+ - lib/winrm/http/auth.rb
108
+ - lib/winrm/http/transport_patch.rb
109
+ - lib/winrm/win32/sspi.rb
110
+ - lib/winrm/winrm_service_patch.rb
111
+ - spec/functional/sspi_nego_encrypt_decrypt_spec.rb
112
+ - spec/spec_helper.rb
113
+ - spec/unit/platform_spec.rb
114
+ - winrm-s.gemspec
115
+ homepage: https://github.com/opscode/winrm-s
116
+ licenses: []
117
+ metadata: {}
118
+ post_install_message:
119
+ rdoc_options: []
120
+ require_paths:
121
+ - lib
122
+ required_ruby_version: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - ! '>='
125
+ - !ruby/object:Gem::Version
126
+ version: '0'
127
+ required_rubygems_version: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ! '>'
130
+ - !ruby/object:Gem::Version
131
+ version: 1.3.1
132
+ requirements: []
133
+ rubyforge_project:
134
+ rubygems_version: 2.1.11
135
+ signing_key:
136
+ specification_version: 4
137
+ summary: Gem that extends the functionality of the WinRM gem to support the Microsoft
138
+ Negotiate protocol when authenticating to a remote WinRM endpoint from a Windows
139
+ system
140
+ test_files:
141
+ - spec/functional/sspi_nego_encrypt_decrypt_spec.rb
142
+ - spec/spec_helper.rb
143
+ - spec/unit/platform_spec.rb
144
+ has_rdoc: true