summaryrefslogtreecommitdiff
path: root/bin
diff options
context:
space:
mode:
authorNathaniel Case <this.is@nathanielca.se>2018-08-10 09:26:58 -0400
committerGitHub <noreply@github.com>2018-08-10 09:26:58 -0400
commitf2211058826944a4e8e9e9b678d26615a29977b3 (patch)
treeb5df7f1f48c805780fc1b36f4fa48a9bf00982b0 /bin
parent77bff99f3c54d4720c7cb4228b1f520d5aa9a765 (diff)
downloadansible-f2211058826944a4e8e9e9b678d26615a29977b3.tar.gz
Prevent data being truncated over persistent connection socket (#43885)
* Change how data is sent to the persistent connection socket. We can't rely on readline(), so send the size of the data first. We can then read that many bytes from the stream on the recieving end. * Set pty to noncanonical mode before sending * Now that we send data length, we don't need a sentinel anymore * Copy socket changes to persistent, too * Use os.write instead of fdopen()ing and using that. * Follow pickle with sha1sum of pickle * Swap order of vars and init being passed to ansible-connection
Diffstat (limited to 'bin')
-rwxr-xr-xbin/ansible-connection39
1 files changed, 20 insertions, 19 deletions
diff --git a/bin/ansible-connection b/bin/ansible-connection
index a9b381c63a..43b3675a21 100755
--- a/bin/ansible-connection
+++ b/bin/ansible-connection
@@ -12,6 +12,7 @@ except Exception:
pass
import fcntl
+import hashlib
import os
import signal
import socket
@@ -36,6 +37,23 @@ from ansible.utils.display import Display
from ansible.utils.jsonrpc import JsonRpcServer
+def read_stream(byte_stream):
+ size = int(byte_stream.readline().strip())
+
+ data = byte_stream.read(size)
+ if len(data) < size:
+ raise Exception("EOF found before data was complete")
+
+ data_hash = to_text(byte_stream.readline().strip())
+ if data_hash != hashlib.sha1(data).hexdigest():
+ raise Exception("Read {0} bytes, but data did not match checksum".format(size))
+
+ # restore escaped loose \r characters
+ data = data.replace(br'\r', b'\r')
+
+ return data
+
+
@contextmanager
def file_lock(lock_path):
"""
@@ -204,25 +222,8 @@ def main():
try:
# read the play context data via stdin, which means depickling it
- cur_line = stdin.readline()
- init_data = b''
-
- while cur_line.strip() != b'#END_INIT#':
- if cur_line == b'':
- raise Exception("EOF found before init data was complete")
- init_data += cur_line
- cur_line = stdin.readline()
-
- cur_line = stdin.readline()
- vars_data = b''
-
- while cur_line.strip() != b'#END_VARS#':
- if cur_line == b'':
- raise Exception("EOF found before vars data was complete")
- vars_data += cur_line
- cur_line = stdin.readline()
- # restore escaped loose \r characters
- vars_data = vars_data.replace(br'\r', b'\r')
+ vars_data = read_stream(stdin)
+ init_data = read_stream(stdin)
if PY3:
pc_data = cPickle.loads(init_data, encoding='bytes')