1
+ from __future__ import annotations
2
+
1
3
import re
2
4
import struct
3
5
from urllib .parse import urlsplit
@@ -12,7 +14,7 @@ class Encryption(object):
12
14
SIXTEN_KB = 16384
13
15
MIME_BOUNDARY = b"--Encrypted Boundary"
14
16
15
- def __init__ (self , session , protocol ) :
17
+ def __init__ (self , session : requests . Session , protocol : str ) -> None :
16
18
"""
17
19
[MS-WSMV] v30.0 2016-07-14
18
20
@@ -51,7 +53,7 @@ def __init__(self, session, protocol):
51
53
else :
52
54
raise WinRMError ("Encryption for protocol '%s' not supported in pywinrm" % protocol )
53
55
54
- def prepare_encrypted_request (self , session , endpoint , message ) :
56
+ def prepare_encrypted_request (self , session : requests . Session , endpoint : str | bytes , message : bytes ) -> requests . PreparedRequest :
55
57
"""
56
58
Creates a prepared request to send to the server with an encrypted message
57
59
and correct headers
@@ -77,28 +79,29 @@ def prepare_encrypted_request(self, session, endpoint, message):
77
79
78
80
request = requests .Request ("POST" , endpoint , data = encrypted_message )
79
81
prepared_request = session .prepare_request (request )
80
- prepared_request .headers ["Content-Length" ] = str (len (prepared_request .body ))
82
+ prepared_request .headers ["Content-Length" ] = str (len (prepared_request .body )) if prepared_request . body else "0"
81
83
prepared_request .headers ["Content-Type" ] = '{0};protocol="{1}";boundary="Encrypted Boundary"' .format (content_type , self .protocol_string .decode ())
82
84
83
85
return prepared_request
84
86
85
- def parse_encrypted_response (self , response ) :
87
+ def parse_encrypted_response (self , response : requests . Response ) -> bytes :
86
88
"""
87
89
Takes in the encrypted response from the server and decrypts it
88
90
89
91
:param response: The response that needs to be decrypted
90
92
:return: The unencrypted message from the server
91
93
"""
92
94
content_type = response .headers ["Content-Type" ]
95
+
93
96
if 'protocol="{0}"' .format (self .protocol_string .decode ()) in content_type :
94
97
host = urlsplit (response .request .url ).hostname
95
98
msg = self ._decrypt_response (response , host )
96
99
else :
97
- msg = response .text
100
+ msg = response .content
98
101
99
102
return msg
100
103
101
- def _encrypt_message (self , message , host ) :
104
+ def _encrypt_message (self , message : bytes , host : str | bytes | None ) -> bytes :
102
105
message_length = str (len (message )).encode ()
103
106
encrypted_stream = self ._build_message (message , host )
104
107
@@ -111,7 +114,7 @@ def _encrypt_message(self, message, host):
111
114
112
115
return message_payload
113
116
114
- def _decrypt_response (self , response , host ) :
117
+ def _decrypt_response (self , response : requests . Response , host : str | bytes | None ) -> bytes :
115
118
parts = response .content .split (self .MIME_BOUNDARY + b"\r \n " )
116
119
parts = list (filter (None , parts )) # filter out empty parts of the split
117
120
message = b""
@@ -139,55 +142,55 @@ def _decrypt_response(self, response, host):
139
142
140
143
return message
141
144
142
- def _decrypt_ntlm_message (self , encrypted_data , host ) :
145
+ def _decrypt_ntlm_message (self , encrypted_data : bytes , host : str | bytes | None ) -> bytes :
143
146
signature_length = struct .unpack ("<i" , encrypted_data [:4 ])[0 ]
144
147
signature = encrypted_data [4 : signature_length + 4 ]
145
148
encrypted_message = encrypted_data [signature_length + 4 :]
146
149
147
- message = self .session .auth .session_security .unwrap (encrypted_message , signature )
150
+ message = self .session .auth .session_security .unwrap (encrypted_message , signature ) # type: ignore[union-attr]
148
151
149
152
return message
150
153
151
- def _decrypt_credssp_message (self , encrypted_data , host ) :
154
+ def _decrypt_credssp_message (self , encrypted_data : bytes , host : str | bytes | None ) -> bytes :
152
155
# trailer_length = struct.unpack("<i", encrypted_data[:4])[0]
153
156
encrypted_message = encrypted_data [4 :]
154
157
155
- credssp_context = self .session .auth .contexts [host ]
158
+ credssp_context = self .session .auth .contexts [host ] # type: ignore[union-attr]
156
159
message = credssp_context .unwrap (encrypted_message )
157
160
158
161
return message
159
162
160
- def _decrypt_kerberos_message (self , encrypted_data , host ) :
163
+ def _decrypt_kerberos_message (self , encrypted_data : bytes , host : str | bytes | None ) -> bytes :
161
164
signature_length = struct .unpack ("<i" , encrypted_data [:4 ])[0 ]
162
165
signature = encrypted_data [4 : signature_length + 4 ]
163
166
encrypted_message = encrypted_data [signature_length + 4 :]
164
167
165
- message = self .session .auth .unwrap_winrm (host , encrypted_message , signature )
168
+ message = self .session .auth .unwrap_winrm (host , encrypted_message , signature ) # type: ignore[union-attr]
166
169
167
170
return message
168
171
169
- def _build_ntlm_message (self , message , host ) :
170
- sealed_message , signature = self .session .auth .session_security .wrap (message )
172
+ def _build_ntlm_message (self , message : bytes , host : str | bytes | None ) -> bytes :
173
+ sealed_message , signature = self .session .auth .session_security .wrap (message ) # type: ignore[union-attr]
171
174
signature_length = struct .pack ("<i" , len (signature ))
172
175
173
176
return signature_length + signature + sealed_message
174
177
175
- def _build_credssp_message (self , message , host ) :
176
- credssp_context = self .session .auth .contexts [host ]
178
+ def _build_credssp_message (self , message : bytes , host : str | bytes | None ) -> bytes :
179
+ credssp_context = self .session .auth .contexts [host ] # type: ignore[union-attr]
177
180
sealed_message = credssp_context .wrap (message )
178
181
179
182
cipher_negotiated = credssp_context .tls_connection .get_cipher_name ()
180
183
trailer_length = self ._get_credssp_trailer_length (len (message ), cipher_negotiated )
181
184
182
185
return struct .pack ("<i" , trailer_length ) + sealed_message
183
186
184
- def _build_kerberos_message (self , message , host ) :
185
- sealed_message , signature = self .session .auth .wrap_winrm (host , message )
187
+ def _build_kerberos_message (self , message : bytes , host : str | bytes | None ) -> bytes :
188
+ sealed_message , signature = self .session .auth .wrap_winrm (host , message ) # type: ignore[union-attr]
186
189
signature_length = struct .pack ("<i" , len (signature ))
187
190
188
191
return signature_length + signature + sealed_message
189
192
190
- def _get_credssp_trailer_length (self , message_length , cipher_suite ) :
193
+ def _get_credssp_trailer_length (self , message_length : int , cipher_suite : str ) -> int :
191
194
# I really don't like the way this works but can't find a better way, MS
192
195
# allows you to get this info through the struct SecPkgContext_StreamSizes
193
196
# but there is no GSSAPI/OpenSSL equivalent so we need to calculate it
0 commit comments