vagrant-unbundled 2.2.6.1 → 2.2.6.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (142) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +11 -9
  3. data/vagrant.gemspec +1 -1
  4. data/vendor/bundle/ruby/2.6.0/bundler/gems/vagrant-spec-abfc34474d12/vagrant-spec.gemspec +1 -1
  5. data/vendor/bundle/ruby/2.6.0/gems/erubi-1.9.0/CHANGELOG +79 -0
  6. data/vendor/bundle/ruby/2.6.0/gems/erubi-1.9.0/MIT-LICENSE +21 -0
  7. data/vendor/bundle/ruby/2.6.0/gems/erubi-1.9.0/README.rdoc +109 -0
  8. data/vendor/bundle/ruby/2.6.0/gems/erubi-1.9.0/Rakefile +78 -0
  9. data/vendor/bundle/ruby/2.6.0/gems/erubi-1.9.0/lib/erubi/capture_end.rb +52 -0
  10. data/vendor/bundle/ruby/2.6.0/gems/erubi-1.9.0/lib/erubi.rb +211 -0
  11. data/vendor/bundle/ruby/2.6.0/gems/erubi-1.9.0/test/test.rb +780 -0
  12. data/vendor/bundle/ruby/2.6.0/gems/rubyzip-2.0.0/README.md +354 -0
  13. data/vendor/bundle/ruby/2.6.0/gems/rubyzip-2.0.0/Rakefile +18 -0
  14. data/vendor/bundle/ruby/2.6.0/gems/rubyzip-2.0.0/TODO +15 -0
  15. data/vendor/bundle/ruby/2.6.0/gems/rubyzip-2.0.0/lib/zip/central_directory.rb +208 -0
  16. data/vendor/bundle/ruby/2.6.0/gems/rubyzip-2.0.0/lib/zip/compressor.rb +9 -0
  17. data/vendor/bundle/ruby/2.6.0/gems/rubyzip-2.0.0/lib/zip/constants.rb +63 -0
  18. data/vendor/bundle/ruby/2.6.0/gems/rubyzip-2.0.0/lib/zip/crypto/encryption.rb +11 -0
  19. data/vendor/bundle/ruby/2.6.0/gems/rubyzip-2.0.0/lib/zip/crypto/null_encryption.rb +43 -0
  20. data/vendor/bundle/ruby/2.6.0/gems/rubyzip-2.0.0/lib/zip/crypto/traditional_encryption.rb +99 -0
  21. data/vendor/bundle/ruby/2.6.0/gems/rubyzip-2.0.0/lib/zip/decompressor.rb +13 -0
  22. data/vendor/bundle/ruby/2.6.0/gems/rubyzip-2.0.0/lib/zip/deflater.rb +34 -0
  23. data/vendor/bundle/ruby/2.6.0/gems/rubyzip-2.0.0/lib/zip/dos_time.rb +48 -0
  24. data/vendor/bundle/ruby/2.6.0/gems/rubyzip-2.0.0/lib/zip/entry.rb +700 -0
  25. data/vendor/bundle/ruby/2.6.0/gems/rubyzip-2.0.0/lib/zip/entry_set.rb +86 -0
  26. data/vendor/bundle/ruby/2.6.0/gems/rubyzip-2.0.0/lib/zip/errors.rb +18 -0
  27. data/vendor/bundle/ruby/2.6.0/gems/rubyzip-2.0.0/lib/zip/extra_field/generic.rb +43 -0
  28. data/vendor/bundle/ruby/2.6.0/gems/rubyzip-2.0.0/lib/zip/extra_field/ntfs.rb +90 -0
  29. data/vendor/bundle/ruby/2.6.0/gems/rubyzip-2.0.0/lib/zip/extra_field/old_unix.rb +44 -0
  30. data/vendor/bundle/ruby/2.6.0/gems/rubyzip-2.0.0/lib/zip/extra_field/universal_time.rb +47 -0
  31. data/vendor/bundle/ruby/2.6.0/gems/rubyzip-2.0.0/lib/zip/extra_field/unix.rb +37 -0
  32. data/vendor/bundle/ruby/2.6.0/gems/rubyzip-2.0.0/lib/zip/extra_field/zip64.rb +68 -0
  33. data/vendor/bundle/ruby/2.6.0/gems/rubyzip-2.0.0/lib/zip/extra_field/zip64_placeholder.rb +15 -0
  34. data/vendor/bundle/ruby/2.6.0/gems/rubyzip-2.0.0/lib/zip/extra_field.rb +101 -0
  35. data/vendor/bundle/ruby/2.6.0/gems/rubyzip-2.0.0/lib/zip/file.rb +443 -0
  36. data/vendor/bundle/ruby/2.6.0/gems/rubyzip-2.0.0/lib/zip/filesystem.rb +627 -0
  37. data/vendor/bundle/ruby/2.6.0/gems/rubyzip-2.0.0/lib/zip/inflater.rb +66 -0
  38. data/vendor/bundle/ruby/2.6.0/gems/rubyzip-2.0.0/lib/zip/input_stream.rb +173 -0
  39. data/vendor/bundle/ruby/2.6.0/gems/rubyzip-2.0.0/lib/zip/ioextras/abstract_input_stream.rb +111 -0
  40. data/vendor/bundle/ruby/2.6.0/gems/rubyzip-2.0.0/lib/zip/ioextras/abstract_output_stream.rb +43 -0
  41. data/vendor/bundle/ruby/2.6.0/gems/rubyzip-2.0.0/lib/zip/ioextras.rb +36 -0
  42. data/vendor/bundle/ruby/2.6.0/gems/rubyzip-2.0.0/lib/zip/null_compressor.rb +15 -0
  43. data/vendor/bundle/ruby/2.6.0/gems/rubyzip-2.0.0/lib/zip/null_decompressor.rb +27 -0
  44. data/vendor/bundle/ruby/2.6.0/gems/rubyzip-2.0.0/lib/zip/null_input_stream.rb +10 -0
  45. data/vendor/bundle/ruby/2.6.0/gems/rubyzip-2.0.0/lib/zip/output_stream.rb +189 -0
  46. data/vendor/bundle/ruby/2.6.0/gems/rubyzip-2.0.0/lib/zip/pass_thru_compressor.rb +23 -0
  47. data/vendor/bundle/ruby/2.6.0/gems/rubyzip-2.0.0/lib/zip/pass_thru_decompressor.rb +40 -0
  48. data/vendor/bundle/ruby/2.6.0/gems/rubyzip-2.0.0/lib/zip/streamable_directory.rb +15 -0
  49. data/vendor/bundle/ruby/2.6.0/gems/rubyzip-2.0.0/lib/zip/streamable_stream.rb +56 -0
  50. data/vendor/bundle/ruby/2.6.0/gems/rubyzip-2.0.0/lib/zip/version.rb +3 -0
  51. data/vendor/bundle/ruby/2.6.0/gems/rubyzip-2.0.0/lib/zip.rb +71 -0
  52. data/vendor/bundle/ruby/2.6.0/gems/rubyzip-2.0.0/samples/example.rb +81 -0
  53. data/vendor/bundle/ruby/2.6.0/gems/rubyzip-2.0.0/samples/example_filesystem.rb +31 -0
  54. data/vendor/bundle/ruby/2.6.0/gems/rubyzip-2.0.0/samples/example_recursive.rb +54 -0
  55. data/vendor/bundle/ruby/2.6.0/gems/rubyzip-2.0.0/samples/gtk_ruby_zip.rb +84 -0
  56. data/vendor/bundle/ruby/2.6.0/gems/rubyzip-2.0.0/samples/qtzip.rb +92 -0
  57. data/vendor/bundle/ruby/2.6.0/gems/rubyzip-2.0.0/samples/write_simple.rb +12 -0
  58. data/vendor/bundle/ruby/2.6.0/gems/rubyzip-2.0.0/samples/zipfind.rb +66 -0
  59. data/vendor/bundle/ruby/2.6.0/gems/winrm-2.3.3/LICENSE +202 -0
  60. data/vendor/bundle/ruby/2.6.0/gems/winrm-2.3.3/README.md +276 -0
  61. data/vendor/bundle/ruby/2.6.0/gems/winrm-2.3.3/bin/rwinrm +90 -0
  62. data/vendor/bundle/ruby/2.6.0/gems/winrm-2.3.3/lib/winrm/connection.rb +84 -0
  63. data/vendor/bundle/ruby/2.6.0/gems/winrm-2.3.3/lib/winrm/connection_opts.rb +90 -0
  64. data/vendor/bundle/ruby/2.6.0/gems/winrm-2.3.3/lib/winrm/exceptions.rb +88 -0
  65. data/vendor/bundle/ruby/2.6.0/gems/winrm-2.3.3/lib/winrm/http/response_handler.rb +127 -0
  66. data/vendor/bundle/ruby/2.6.0/gems/winrm-2.3.3/lib/winrm/http/transport.rb +462 -0
  67. data/vendor/bundle/ruby/2.6.0/gems/winrm-2.3.3/lib/winrm/http/transport_factory.rb +64 -0
  68. data/vendor/bundle/ruby/2.6.0/gems/winrm-2.3.3/lib/winrm/output.rb +58 -0
  69. data/vendor/bundle/ruby/2.6.0/gems/winrm-2.3.3/lib/winrm/psrp/create_pipeline.xml.erb +167 -0
  70. data/vendor/bundle/ruby/2.6.0/gems/winrm-2.3.3/lib/winrm/psrp/fragment.rb +68 -0
  71. data/vendor/bundle/ruby/2.6.0/gems/winrm-2.3.3/lib/winrm/psrp/init_runspace_pool.xml.erb +224 -0
  72. data/vendor/bundle/ruby/2.6.0/gems/winrm-2.3.3/lib/winrm/psrp/message.rb +128 -0
  73. data/vendor/bundle/ruby/2.6.0/gems/winrm-2.3.3/lib/winrm/psrp/message_data/base.rb +47 -0
  74. data/vendor/bundle/ruby/2.6.0/gems/winrm-2.3.3/lib/winrm/psrp/message_data/error_record.rb +66 -0
  75. data/vendor/bundle/ruby/2.6.0/gems/winrm-2.3.3/lib/winrm/psrp/message_data/pipeline_host_call.rb +30 -0
  76. data/vendor/bundle/ruby/2.6.0/gems/winrm-2.3.3/lib/winrm/psrp/message_data/pipeline_output.rb +48 -0
  77. data/vendor/bundle/ruby/2.6.0/gems/winrm-2.3.3/lib/winrm/psrp/message_data/pipeline_state.rb +38 -0
  78. data/vendor/bundle/ruby/2.6.0/gems/winrm-2.3.3/lib/winrm/psrp/message_data/runspacepool_host_call.rb +30 -0
  79. data/vendor/bundle/ruby/2.6.0/gems/winrm-2.3.3/lib/winrm/psrp/message_data/runspacepool_state.rb +37 -0
  80. data/vendor/bundle/ruby/2.6.0/gems/winrm-2.3.3/lib/winrm/psrp/message_data/session_capability.rb +34 -0
  81. data/vendor/bundle/ruby/2.6.0/gems/winrm-2.3.3/lib/winrm/psrp/message_data.rb +40 -0
  82. data/vendor/bundle/ruby/2.6.0/gems/winrm-2.3.3/lib/winrm/psrp/message_defragmenter.rb +62 -0
  83. data/vendor/bundle/ruby/2.6.0/gems/winrm-2.3.3/lib/winrm/psrp/message_factory.rb +86 -0
  84. data/vendor/bundle/ruby/2.6.0/gems/winrm-2.3.3/lib/winrm/psrp/message_fragmenter.rb +58 -0
  85. data/vendor/bundle/ruby/2.6.0/gems/winrm-2.3.3/lib/winrm/psrp/powershell_output_decoder.rb +142 -0
  86. data/vendor/bundle/ruby/2.6.0/gems/winrm-2.3.3/lib/winrm/psrp/receive_response_reader.rb +95 -0
  87. data/vendor/bundle/ruby/2.6.0/gems/winrm-2.3.3/lib/winrm/psrp/session_capability.xml.erb +7 -0
  88. data/vendor/bundle/ruby/2.6.0/gems/winrm-2.3.3/lib/winrm/psrp/uuid.rb +39 -0
  89. data/vendor/bundle/ruby/2.6.0/gems/winrm-2.3.3/lib/winrm/shells/base.rb +187 -0
  90. data/vendor/bundle/ruby/2.6.0/gems/winrm-2.3.3/lib/winrm/shells/cmd.rb +63 -0
  91. data/vendor/bundle/ruby/2.6.0/gems/winrm-2.3.3/lib/winrm/shells/power_shell.rb +206 -0
  92. data/vendor/bundle/ruby/2.6.0/gems/winrm-2.3.3/lib/winrm/shells/retryable.rb +44 -0
  93. data/vendor/bundle/ruby/2.6.0/gems/winrm-2.3.3/lib/winrm/shells/shell_factory.rb +56 -0
  94. data/vendor/bundle/ruby/2.6.0/gems/winrm-2.3.3/lib/winrm/version.rb +5 -0
  95. data/vendor/bundle/ruby/2.6.0/gems/winrm-2.3.3/lib/winrm/wsmv/base.rb +57 -0
  96. data/vendor/bundle/ruby/2.6.0/gems/winrm-2.3.3/lib/winrm/wsmv/cleanup_command.rb +60 -0
  97. data/vendor/bundle/ruby/2.6.0/gems/winrm-2.3.3/lib/winrm/wsmv/close_shell.rb +49 -0
  98. data/vendor/bundle/ruby/2.6.0/gems/winrm-2.3.3/lib/winrm/wsmv/command.rb +100 -0
  99. data/vendor/bundle/ruby/2.6.0/gems/winrm-2.3.3/lib/winrm/wsmv/command_output.rb +75 -0
  100. data/vendor/bundle/ruby/2.6.0/gems/winrm-2.3.3/lib/winrm/wsmv/command_output_decoder.rb +54 -0
  101. data/vendor/bundle/ruby/2.6.0/gems/winrm-2.3.3/lib/winrm/wsmv/configuration.rb +44 -0
  102. data/vendor/bundle/ruby/2.6.0/gems/winrm-2.3.3/lib/winrm/wsmv/create_pipeline.rb +64 -0
  103. data/vendor/bundle/ruby/2.6.0/gems/winrm-2.3.3/lib/winrm/wsmv/create_shell.rb +115 -0
  104. data/vendor/bundle/ruby/2.6.0/gems/winrm-2.3.3/lib/winrm/wsmv/header.rb +213 -0
  105. data/vendor/bundle/ruby/2.6.0/gems/winrm-2.3.3/lib/winrm/wsmv/init_runspace_pool.rb +96 -0
  106. data/vendor/bundle/ruby/2.6.0/gems/winrm-2.3.3/lib/winrm/wsmv/iso8601_duration.rb +58 -0
  107. data/vendor/bundle/ruby/2.6.0/gems/winrm-2.3.3/lib/winrm/wsmv/keep_alive.rb +66 -0
  108. data/vendor/bundle/ruby/2.6.0/gems/winrm-2.3.3/lib/winrm/wsmv/receive_response_reader.rb +128 -0
  109. data/vendor/bundle/ruby/2.6.0/gems/winrm-2.3.3/lib/winrm/wsmv/send_data.rb +66 -0
  110. data/vendor/bundle/ruby/2.6.0/gems/winrm-2.3.3/lib/winrm/wsmv/soap.rb +49 -0
  111. data/vendor/bundle/ruby/2.6.0/gems/winrm-2.3.3/lib/winrm/wsmv/wql_pull.rb +54 -0
  112. data/vendor/bundle/ruby/2.6.0/gems/winrm-2.3.3/lib/winrm/wsmv/wql_query.rb +98 -0
  113. data/vendor/bundle/ruby/2.6.0/gems/winrm-2.3.3/lib/winrm/wsmv/write_stdin.rb +86 -0
  114. data/vendor/bundle/ruby/2.6.0/gems/winrm-2.3.3/lib/winrm.rb +37 -0
  115. data/vendor/bundle/ruby/2.6.0/gems/winrm-elevated-1.1.2/LICENSE +202 -0
  116. data/vendor/bundle/ruby/2.6.0/gems/winrm-elevated-1.1.2/README.md +99 -0
  117. data/vendor/bundle/ruby/2.6.0/gems/winrm-elevated-1.1.2/lib/winrm/shells/elevated.rb +108 -0
  118. data/vendor/bundle/ruby/2.6.0/gems/winrm-elevated-1.1.2/lib/winrm-elevated/scripts/elevated_shell.ps1 +116 -0
  119. data/vendor/bundle/ruby/2.6.0/gems/winrm-elevated-1.1.2/lib/winrm-elevated.rb +17 -0
  120. data/vendor/bundle/ruby/2.6.0/gems/winrm-fs-1.3.4/LICENSE +202 -0
  121. data/vendor/bundle/ruby/2.6.0/gems/winrm-fs-1.3.4/README.md +82 -0
  122. data/vendor/bundle/ruby/2.6.0/gems/winrm-fs-1.3.4/bin/rwinrmcp +87 -0
  123. data/vendor/bundle/ruby/2.6.0/gems/winrm-fs-1.3.4/lib/winrm-fs/core/file_transporter.rb +569 -0
  124. data/vendor/bundle/ruby/2.6.0/gems/winrm-fs-1.3.4/lib/winrm-fs/core/tmp_zip.rb +178 -0
  125. data/vendor/bundle/ruby/2.6.0/gems/winrm-fs-1.3.4/lib/winrm-fs/exceptions.rb +29 -0
  126. data/vendor/bundle/ruby/2.6.0/gems/winrm-fs-1.3.4/lib/winrm-fs/file_manager.rb +158 -0
  127. data/vendor/bundle/ruby/2.6.0/gems/winrm-fs-1.3.4/lib/winrm-fs/scripts/check_files.ps1.erb +49 -0
  128. data/vendor/bundle/ruby/2.6.0/gems/winrm-fs-1.3.4/lib/winrm-fs/scripts/checksum.ps1.erb +13 -0
  129. data/vendor/bundle/ruby/2.6.0/gems/winrm-fs-1.3.4/lib/winrm-fs/scripts/create_dir.ps1.erb +6 -0
  130. data/vendor/bundle/ruby/2.6.0/gems/winrm-fs-1.3.4/lib/winrm-fs/scripts/delete.ps1.erb +6 -0
  131. data/vendor/bundle/ruby/2.6.0/gems/winrm-fs-1.3.4/lib/winrm-fs/scripts/download.ps1.erb +17 -0
  132. data/vendor/bundle/ruby/2.6.0/gems/winrm-fs-1.3.4/lib/winrm-fs/scripts/exists.ps1.erb +10 -0
  133. data/vendor/bundle/ruby/2.6.0/gems/winrm-fs-1.3.4/lib/winrm-fs/scripts/extract_files.ps1.erb +52 -0
  134. data/vendor/bundle/ruby/2.6.0/gems/winrm-fs-1.3.4/lib/winrm-fs/scripts/scripts.rb +47 -0
  135. data/vendor/bundle/ruby/2.6.0/gems/winrm-fs-1.3.4/lib/winrm-fs.rb +29 -0
  136. data/vendor/bundle/ruby/2.6.0/specifications/erubi-1.9.0.gemspec +38 -0
  137. data/vendor/bundle/ruby/2.6.0/specifications/rubyzip-2.0.0.gemspec +45 -0
  138. data/vendor/bundle/ruby/2.6.0/specifications/winrm-2.3.3.gemspec +73 -0
  139. data/vendor/bundle/ruby/2.6.0/specifications/winrm-elevated-1.1.2.gemspec +50 -0
  140. data/vendor/bundle/ruby/2.6.0/specifications/winrm-fs-1.3.4.gemspec +58 -0
  141. data/version.txt +1 -1
  142. metadata +142 -6
@@ -0,0 +1,462 @@
1
+ # Copyright 2010 Dan Wanek <dan.wanek@gmail.com>
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require 'httpclient'
16
+ require_relative 'response_handler'
17
+
18
+ module WinRM
19
+ module HTTP
20
+ # A generic HTTP transport that utilized HTTPClient to send messages back and forth.
21
+ # This backend will maintain state for every WinRMWebService instance that is instantiated so it
22
+ # is possible to use GSSAPI with Keep-Alive.
23
+ class HttpTransport
24
+ attr_reader :endpoint
25
+
26
+ def initialize(endpoint, options)
27
+ @endpoint = endpoint.is_a?(String) ? URI.parse(endpoint) : endpoint
28
+ @httpcli = HTTPClient.new(agent_name: 'Ruby WinRM Client')
29
+ @logger = Logging.logger[self]
30
+ @httpcli.receive_timeout = options[:receive_timeout]
31
+ end
32
+
33
+ # Sends the SOAP payload to the WinRM service and returns the service's
34
+ # SOAP response. If an error occurrs an appropriate error is raised.
35
+ #
36
+ # @param [String] The XML SOAP message
37
+ # @returns [REXML::Document] The parsed response body
38
+ def send_request(message)
39
+ ssl_peer_fingerprint_verification!
40
+ log_soap_message(message)
41
+ hdr = { 'Content-Type' => 'application/soap+xml;charset=UTF-8',
42
+ 'Content-Length' => message.bytesize }
43
+ # We need to add this header if using Client Certificate authentication
44
+ unless @httpcli.ssl_config.client_cert.nil?
45
+ hdr['Authorization'] = 'http://schemas.dmtf.org/wbem/wsman/1/wsman/secprofile/https/mutual'
46
+ end
47
+
48
+ resp = @httpcli.post(@endpoint, message, hdr)
49
+ log_soap_message(resp.http_body.content)
50
+ verify_ssl_fingerprint(resp.peer_cert)
51
+ handler = WinRM::ResponseHandler.new(resp.http_body.content, resp.status)
52
+ handler.parse_to_xml
53
+ end
54
+
55
+ # We'll need this to force basic authentication if desired
56
+ def basic_auth_only!
57
+ auths = @httpcli.www_auth.instance_variable_get('@authenticator')
58
+ auths.delete_if { |i| i.scheme !~ /basic/i }
59
+ end
60
+
61
+ # Disable SSPI Auth
62
+ def no_sspi_auth!
63
+ auths = @httpcli.www_auth.instance_variable_get('@authenticator')
64
+ auths.delete_if { |i| i.is_a? HTTPClient::SSPINegotiateAuth }
65
+ end
66
+
67
+ # Disable SSL Peer Verification
68
+ def no_ssl_peer_verification!
69
+ @httpcli.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_NONE
70
+ end
71
+
72
+ # SSL Peer Fingerprint Verification prior to connecting
73
+ def ssl_peer_fingerprint_verification!
74
+ return unless @ssl_peer_fingerprint && !@ssl_peer_fingerprint_verified
75
+
76
+ with_untrusted_ssl_connection do |connection|
77
+ connection_cert = connection.peer_cert
78
+ verify_ssl_fingerprint(connection_cert)
79
+ end
80
+ @logger.info("initial ssl fingerprint #{@ssl_peer_fingerprint} verified\n")
81
+ @ssl_peer_fingerprint_verified = true
82
+ no_ssl_peer_verification!
83
+ end
84
+
85
+ # Connect without verification to retrieve untrusted ssl context
86
+ def with_untrusted_ssl_connection
87
+ noverify_peer_context = OpenSSL::SSL::SSLContext.new
88
+ noverify_peer_context.verify_mode = OpenSSL::SSL::VERIFY_NONE
89
+ tcp_connection = TCPSocket.new(@endpoint.host, @endpoint.port)
90
+ begin
91
+ ssl_connection = OpenSSL::SSL::SSLSocket.new(tcp_connection, noverify_peer_context)
92
+ ssl_connection.connect
93
+ yield ssl_connection
94
+ ensure
95
+ tcp_connection.close
96
+ end
97
+ end
98
+
99
+ # compare @ssl_peer_fingerprint to current ssl context
100
+ def verify_ssl_fingerprint(cert)
101
+ return unless @ssl_peer_fingerprint
102
+
103
+ conn_fingerprint = OpenSSL::Digest::SHA1.new(cert.to_der).to_s
104
+ return unless @ssl_peer_fingerprint.casecmp(conn_fingerprint) != 0
105
+
106
+ raise "ssl fingerprint mismatch!!!!\n"
107
+ end
108
+
109
+ protected
110
+
111
+ def body(message, length, type = 'application/HTTP-SPNEGO-session-encrypted')
112
+ [
113
+ '--Encrypted Boundary',
114
+ "Content-Type: #{type}",
115
+ "OriginalContent: type=application/soap+xml;charset=UTF-8;Length=#{length}",
116
+ '--Encrypted Boundary',
117
+ 'Content-Type: application/octet-stream',
118
+ "#{message}--Encrypted Boundary--"
119
+ ].join("\r\n").concat("\r\n")
120
+ end
121
+
122
+ def log_soap_message(message)
123
+ return unless @logger.debug?
124
+
125
+ xml_msg = REXML::Document.new(message)
126
+ formatter = REXML::Formatters::Pretty.new(2)
127
+ formatter.compact = true
128
+ formatter.write(xml_msg, @logger)
129
+ @logger.debug("\n")
130
+ rescue StandardError => e
131
+ @logger.debug("Couldn't log SOAP request/response: #{e.message} - #{message}")
132
+ end
133
+ end
134
+
135
+ # Plain text, insecure, HTTP transport
136
+ class HttpPlaintext < HttpTransport
137
+ def initialize(endpoint, user, pass, opts)
138
+ super(endpoint, opts)
139
+ @httpcli.set_auth(nil, user, pass)
140
+ no_sspi_auth! if opts[:disable_sspi]
141
+ basic_auth_only! if opts[:basic_auth_only]
142
+ no_ssl_peer_verification! if opts[:no_ssl_peer_verification]
143
+ end
144
+ end
145
+
146
+ # NTLM/Negotiate, secure, HTTP transport
147
+ class HttpNegotiate < HttpTransport
148
+ def initialize(endpoint, user, pass, opts)
149
+ super(endpoint, opts)
150
+ require 'rubyntlm'
151
+ no_sspi_auth!
152
+
153
+ user_parts = user.split('\\')
154
+ if user_parts.length > 1
155
+ opts[:domain] = user_parts[0]
156
+ user = user_parts[1]
157
+ end
158
+
159
+ @ntlmcli = Net::NTLM::Client.new(user, pass, opts)
160
+ @retryable = true
161
+ no_ssl_peer_verification! if opts[:no_ssl_peer_verification]
162
+ @ssl_peer_fingerprint = opts[:ssl_peer_fingerprint]
163
+ @httpcli.ssl_config.set_trust_ca(opts[:ca_trust_path]) if opts[:ca_trust_path]
164
+ end
165
+
166
+ def send_request(message)
167
+ ssl_peer_fingerprint_verification!
168
+ init_auth if @ntlmcli.session.nil?
169
+ log_soap_message(message)
170
+
171
+ hdr = {
172
+ 'Content-Type' => 'multipart/encrypted;'\
173
+ 'protocol="application/HTTP-SPNEGO-session-encrypted";boundary="Encrypted Boundary"'
174
+ }
175
+
176
+ resp = @httpcli.post(@endpoint, body(seal(message), message.bytesize), hdr)
177
+ verify_ssl_fingerprint(resp.peer_cert)
178
+ if resp.status == 401 && @retryable
179
+ @retryable = false
180
+ init_auth
181
+ send_request(message)
182
+ else
183
+ @retryable = true
184
+ decrypted_body = winrm_decrypt(resp)
185
+ log_soap_message(decrypted_body)
186
+ WinRM::ResponseHandler.new(decrypted_body, resp.status).parse_to_xml
187
+ end
188
+ end
189
+
190
+ private
191
+
192
+ def seal(message)
193
+ emessage = @ntlmcli.session.seal_message message
194
+ signature = @ntlmcli.session.sign_message message
195
+ "\x10\x00\x00\x00#{signature}#{emessage}"
196
+ end
197
+
198
+ def winrm_decrypt(resp)
199
+ # OMI server doesn't always respond to encrypted messages with encrypted responses over SSL
200
+ return resp.body if resp.header['Content-Type'].first =~ %r{\Aapplication\/soap\+xml}i
201
+ return '' if resp.body.empty?
202
+
203
+ str = resp.body.force_encoding('BINARY')
204
+ str.sub!(%r{^.*Content-Type: application\/octet-stream\r\n(.*)--Encrypted.*$}m, '\1')
205
+
206
+ signature = str[4..19]
207
+ message = @ntlmcli.session.unseal_message str[20..-1]
208
+ return message if @ntlmcli.session.verify_signature(signature, message)
209
+
210
+ raise WinRMHTTPTransportError, 'Could not decrypt NTLM message.'
211
+ end
212
+
213
+ def issue_challenge_response(negotiate)
214
+ auth_header = {
215
+ 'Authorization' => "Negotiate #{negotiate.encode64}",
216
+ 'Content-Type' => 'application/soap+xml;charset=UTF-8'
217
+ }
218
+
219
+ # OMI Server on Linux requires an empty payload with the new auth header to proceed
220
+ # because the config check for max payload size will otherwise break the auth handshake
221
+ # given the OMI server does not support that check
222
+ @httpcli.post(@endpoint, '', auth_header)
223
+
224
+ # return an empty hash of headers for subsequent requests to use
225
+ {}
226
+ end
227
+
228
+ def init_auth
229
+ @logger.debug "Initializing Negotiate for #{@endpoint}"
230
+ auth1 = @ntlmcli.init_context
231
+ hdr = {
232
+ 'Authorization' => "Negotiate #{auth1.encode64}",
233
+ 'Content-Type' => 'application/soap+xml;charset=UTF-8'
234
+ }
235
+ @logger.debug 'Sending HTTP POST for Negotiate Authentication'
236
+ r = @httpcli.post(@endpoint, '', hdr)
237
+ verify_ssl_fingerprint(r.peer_cert)
238
+ auth_header = r.header['WWW-Authenticate'].pop
239
+ unless auth_header
240
+ msg = "Unable to parse authorization header. Headers: #{r.headers}\r\nBody: #{r.body}"
241
+ raise WinRMHTTPTransportError.new(msg, r.status_code)
242
+ end
243
+ itok = auth_header.split.last
244
+ auth3 = @ntlmcli.init_context(itok, channel_binding(r))
245
+ issue_challenge_response(auth3)
246
+ end
247
+
248
+ def channel_binding(response)
249
+ if response.peer_cert.nil?
250
+ nil
251
+ else
252
+ cert = if RUBY_PLATFORM == 'java'
253
+ OpenSSL::X509::Certificate.new(response.peer_cert.cert.getEncoded)
254
+ else
255
+ response.peer_cert
256
+ end
257
+ Net::NTLM::ChannelBinding.create(OpenSSL::X509::Certificate.new(cert))
258
+ end
259
+ end
260
+ end
261
+
262
+ # Uses SSL to secure the transport
263
+ class BasicAuthSSL < HttpTransport
264
+ def initialize(endpoint, user, pass, opts)
265
+ super(endpoint, opts)
266
+ @httpcli.set_auth(endpoint, user, pass)
267
+ basic_auth_only!
268
+ no_ssl_peer_verification! if opts[:no_ssl_peer_verification]
269
+ @ssl_peer_fingerprint = opts[:ssl_peer_fingerprint]
270
+ @httpcli.ssl_config.set_trust_ca(opts[:ca_trust_path]) if opts[:ca_trust_path]
271
+ end
272
+ end
273
+
274
+ # Uses Client Certificate to authenticate and SSL to secure the transport
275
+ class ClientCertAuthSSL < HttpTransport
276
+ def initialize(endpoint, client_cert, client_key, key_pass, opts)
277
+ super(endpoint, opts)
278
+ @httpcli.ssl_config.set_client_cert_file(client_cert, client_key, key_pass)
279
+ @httpcli.www_auth.instance_variable_set('@authenticator', [])
280
+ no_ssl_peer_verification! if opts[:no_ssl_peer_verification]
281
+ @ssl_peer_fingerprint = opts[:ssl_peer_fingerprint]
282
+ @httpcli.ssl_config.set_trust_ca(opts[:ca_trust_path]) if opts[:ca_trust_path]
283
+ end
284
+ end
285
+
286
+ # Uses Kerberos/GSSAPI to authenticate and encrypt messages
287
+ class HttpGSSAPI < HttpTransport
288
+ # @param [String,URI] endpoint the WinRM webservice endpoint
289
+ # @param [String] realm the Kerberos realm we are authenticating to
290
+ # @param [String<optional>] service the service name, default is HTTP
291
+ def initialize(endpoint, realm, opts, service = nil)
292
+ require 'gssapi'
293
+ require 'gssapi/extensions'
294
+
295
+ super(endpoint, opts)
296
+ # Remove the GSSAPI auth from HTTPClient because we are doing our own thing
297
+ no_sspi_auth!
298
+ service ||= 'HTTP'
299
+ @service = "#{service}/#{@endpoint.host}@#{realm}"
300
+ no_ssl_peer_verification! if opts[:no_ssl_peer_verification]
301
+ init_krb
302
+ end
303
+
304
+ # Sends the SOAP payload to the WinRM service and returns the service's
305
+ # SOAP response. If an error occurrs an appropriate error is raised.
306
+ #
307
+ # @param [String] The XML SOAP message
308
+ # @returns [REXML::Document] The parsed response body
309
+ def send_request(message)
310
+ resp = send_kerberos_request(message)
311
+
312
+ if resp.status == 401
313
+ @logger.debug 'Got 401 - reinitializing Kerberos and retrying one more time'
314
+ init_krb
315
+ resp = send_kerberos_request(message)
316
+ end
317
+
318
+ handler = WinRM::ResponseHandler.new(winrm_decrypt(resp.http_body.content), resp.status)
319
+ handler.parse_to_xml
320
+ end
321
+
322
+ private
323
+
324
+ # Sends the SOAP payload to the WinRM service and returns the service's
325
+ # HTTP response.
326
+ #
327
+ # @param [String] The XML SOAP message
328
+ # @returns [Object] The HTTP response object
329
+ def send_kerberos_request(message)
330
+ log_soap_message(message)
331
+ original_length = message.bytesize
332
+ pad_len, emsg = winrm_encrypt(message)
333
+ req_length = original_length + pad_len
334
+ hdr = {
335
+ 'Connection' => 'Keep-Alive',
336
+ 'Content-Type' => 'multipart/encrypted;' \
337
+ 'protocol="application/HTTP-Kerberos-session-encrypted";boundary="Encrypted Boundary"'
338
+ }
339
+
340
+ resp = @httpcli.post(
341
+ @endpoint,
342
+ body(emsg, req_length, 'application/HTTP-Kerberos-session-encrypted'),
343
+ hdr
344
+ )
345
+ log_soap_message(resp.http_body.content)
346
+ resp
347
+ end
348
+
349
+ def init_krb
350
+ @logger.debug "Initializing Kerberos for #{@service}"
351
+ @gsscli = GSSAPI::Simple.new(@endpoint.host, @service)
352
+ token = @gsscli.init_context
353
+ auth = Base64.strict_encode64 token
354
+
355
+ hdr = {
356
+ 'Authorization' => "Kerberos #{auth}",
357
+ 'Connection' => 'Keep-Alive',
358
+ 'Content-Type' => 'application/soap+xml;charset=UTF-8'
359
+ }
360
+ @logger.debug 'Sending HTTP POST for Kerberos Authentication'
361
+ r = @httpcli.post(@endpoint, '', hdr)
362
+ itok = r.header['WWW-Authenticate'].pop
363
+ itok = itok.split.last
364
+ itok = Base64.strict_decode64(itok)
365
+ @gsscli.init_context(itok)
366
+ end
367
+
368
+ # rubocop:disable Metrics/MethodLength
369
+ # rubocop:disable Metrics/AbcSize
370
+
371
+ # @return [String] the encrypted request string
372
+ def winrm_encrypt(str)
373
+ @logger.debug "Encrypting SOAP message:\n#{str}"
374
+ iov_cnt = 3
375
+ iov = FFI::MemoryPointer.new(GSSAPI::LibGSSAPI::GssIOVBufferDesc.size * iov_cnt)
376
+
377
+ iov0 = GSSAPI::LibGSSAPI::GssIOVBufferDesc.new(FFI::Pointer.new(iov.address))
378
+ iov0[:type] = (GSSAPI::LibGSSAPI::GSS_IOV_BUFFER_TYPE_HEADER | \
379
+ GSSAPI::LibGSSAPI::GSS_IOV_BUFFER_FLAG_ALLOCATE)
380
+
381
+ iov1 = GSSAPI::LibGSSAPI::GssIOVBufferDesc.new(
382
+ FFI::Pointer.new(iov.address + (GSSAPI::LibGSSAPI::GssIOVBufferDesc.size * 1))
383
+ )
384
+ iov1[:type] = GSSAPI::LibGSSAPI::GSS_IOV_BUFFER_TYPE_DATA
385
+ iov1[:buffer].value = str
386
+
387
+ iov2 = GSSAPI::LibGSSAPI::GssIOVBufferDesc.new(
388
+ FFI::Pointer.new(iov.address + (GSSAPI::LibGSSAPI::GssIOVBufferDesc.size * 2))
389
+ )
390
+ iov2[:type] = (GSSAPI::LibGSSAPI::GSS_IOV_BUFFER_TYPE_PADDING | \
391
+ GSSAPI::LibGSSAPI::GSS_IOV_BUFFER_FLAG_ALLOCATE)
392
+
393
+ conf_state = FFI::MemoryPointer.new :uint32
394
+ min_stat = FFI::MemoryPointer.new :uint32
395
+
396
+ GSSAPI::LibGSSAPI.gss_wrap_iov(
397
+ min_stat,
398
+ @gsscli.context,
399
+ 1,
400
+ GSSAPI::LibGSSAPI::GSS_C_QOP_DEFAULT,
401
+ conf_state,
402
+ iov,
403
+ iov_cnt
404
+ )
405
+
406
+ token = [iov0[:buffer].length].pack('L')
407
+ token += iov0[:buffer].value
408
+ token += iov1[:buffer].value
409
+ pad_len = iov2[:buffer].length
410
+ token += iov2[:buffer].value if pad_len > 0
411
+ [pad_len, token]
412
+ end
413
+
414
+ # @return [String] the unencrypted response string
415
+ def winrm_decrypt(str)
416
+ @logger.debug "Decrypting SOAP message:\n#{str}"
417
+ iov_cnt = 3
418
+ iov = FFI::MemoryPointer.new(GSSAPI::LibGSSAPI::GssIOVBufferDesc.size * iov_cnt)
419
+
420
+ iov0 = GSSAPI::LibGSSAPI::GssIOVBufferDesc.new(FFI::Pointer.new(iov.address))
421
+ iov0[:type] = (GSSAPI::LibGSSAPI::GSS_IOV_BUFFER_TYPE_HEADER | \
422
+ GSSAPI::LibGSSAPI::GSS_IOV_BUFFER_FLAG_ALLOCATE)
423
+
424
+ iov1 = GSSAPI::LibGSSAPI::GssIOVBufferDesc.new(
425
+ FFI::Pointer.new(iov.address + (GSSAPI::LibGSSAPI::GssIOVBufferDesc.size * 1))
426
+ )
427
+ iov1[:type] = GSSAPI::LibGSSAPI::GSS_IOV_BUFFER_TYPE_DATA
428
+
429
+ iov2 = GSSAPI::LibGSSAPI::GssIOVBufferDesc.new(
430
+ FFI::Pointer.new(iov.address + (GSSAPI::LibGSSAPI::GssIOVBufferDesc.size * 2))
431
+ )
432
+ iov2[:type] = GSSAPI::LibGSSAPI::GSS_IOV_BUFFER_TYPE_DATA
433
+
434
+ str.force_encoding('BINARY')
435
+ str.sub!(%r{^.*Content-Type: application\/octet-stream\r\n(.*)--Encrypted.*$}m, '\1')
436
+
437
+ len = str.unpack('L').first
438
+ iov_data = str.unpack("La#{len}a*")
439
+ iov0[:buffer].value = iov_data[1]
440
+ iov1[:buffer].value = iov_data[2]
441
+
442
+ min_stat = FFI::MemoryPointer.new :uint32
443
+ conf_state = FFI::MemoryPointer.new :uint32
444
+ conf_state.write_int(1)
445
+ qop_state = FFI::MemoryPointer.new :uint32
446
+ qop_state.write_int(0)
447
+
448
+ maj_stat = GSSAPI::LibGSSAPI.gss_unwrap_iov(
449
+ min_stat, @gsscli.context, conf_state, qop_state, iov, iov_cnt
450
+ )
451
+
452
+ @logger.debug "SOAP message decrypted (MAJ: #{maj_stat}, " \
453
+ "MIN: #{min_stat.read_int}):\n#{iov1[:buffer].value}"
454
+
455
+ iov1[:buffer].value
456
+ end
457
+ # rubocop:enable Metrics/MethodLength
458
+ # rubocop:enable Metrics/AbcSize
459
+ end
460
+ end
461
+ end
462
+ # WinRM
@@ -0,0 +1,64 @@
1
+ # Copyright 2016 Shawn Neal <sneal@sneal.net>
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require_relative 'transport'
16
+
17
+ module WinRM
18
+ module HTTP
19
+ # Factory for creating a HTTP transport that can be used for WinRM SOAP calls.
20
+ class TransportFactory
21
+ # Creates a new WinRM HTTP transport using the specified connection options.
22
+ # @param connection_opts [ConnectionOpts|Hash] The connection ConnectionOpts.
23
+ # @return [HttpTransport] A transport instance for making WinRM calls.
24
+ def create_transport(connection_opts)
25
+ transport = connection_opts[:transport]
26
+ validate_transport!(transport)
27
+ send "init_#{transport}_transport", connection_opts
28
+ end
29
+
30
+ private
31
+
32
+ def init_negotiate_transport(opts)
33
+ HTTP::HttpNegotiate.new(opts[:endpoint], opts[:user], opts[:password], opts)
34
+ end
35
+
36
+ def init_kerberos_transport(opts)
37
+ HTTP::HttpGSSAPI.new(opts[:endpoint], opts[:realm], opts, opts[:service])
38
+ end
39
+
40
+ def init_plaintext_transport(opts)
41
+ HTTP::HttpPlaintext.new(opts[:endpoint], opts[:user], opts[:password], opts)
42
+ end
43
+
44
+ def init_ssl_transport(opts)
45
+ if opts[:basic_auth_only]
46
+ HTTP::BasicAuthSSL.new(opts[:endpoint], opts[:user], opts[:password], opts)
47
+ elsif opts[:client_cert]
48
+ HTTP::ClientCertAuthSSL.new(opts[:endpoint], opts[:client_cert],
49
+ opts[:client_key], opts[:key_pass], opts)
50
+ else
51
+ HTTP::HttpNegotiate.new(opts[:endpoint], opts[:user], opts[:password], opts)
52
+ end
53
+ end
54
+
55
+ def validate_transport!(transport)
56
+ valid = private_methods
57
+ .select { |m| m.to_s.start_with?('init_') && m.to_s.end_with?('_transport') }
58
+ .map { |tm| tm.to_s.split('_')[1] }
59
+
60
+ raise WinRM::InvalidTransportError.new(transport, valid) unless valid.include?(transport.to_s)
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,58 @@
1
+ # Copyright 2014 Max Lincoln <max@devopsy.com>
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module WinRM
16
+ # This class holds raw output and has convenience methods to parse.
17
+ class Output
18
+ def initialize
19
+ @data = []
20
+ end
21
+
22
+ # @return [Integer] exitcode returned from command
23
+ attr_reader :exitcode
24
+
25
+ # @return [String] Aggregated stdout and stderr streams
26
+ def output
27
+ @data.flat_map do |line|
28
+ [line[:stdout], line[:stderr]]
29
+ end.compact.join
30
+ end
31
+
32
+ # @return [String] stdout stream output
33
+ def stdout
34
+ @data.map do |line|
35
+ line[:stdout]
36
+ end.compact.join
37
+ end
38
+
39
+ # @return [String] stderr stream output
40
+ def stderr
41
+ @data.map do |line|
42
+ line[:stderr]
43
+ end.compact.join
44
+ end
45
+
46
+ # Sets the exitcode
47
+ def exitcode=(code)
48
+ raise WinRM::InvalidExitCode unless code.is_a? Integer
49
+
50
+ @exitcode = code
51
+ end
52
+
53
+ # Appends stream data to the output
54
+ def <<(data)
55
+ @data << data
56
+ end
57
+ end
58
+ end