diff options
author | Nathaniel Case <this.is@nathanielca.se> | 2018-08-10 09:26:58 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-08-10 09:26:58 -0400 |
commit | f2211058826944a4e8e9e9b678d26615a29977b3 (patch) | |
tree | b5df7f1f48c805780fc1b36f4fa48a9bf00982b0 /bin | |
parent | 77bff99f3c54d4720c7cb4228b1f520d5aa9a765 (diff) | |
download | ansible-f2211058826944a4e8e9e9b678d26615a29977b3.zip |
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-x | bin/ansible-connection | 39 |
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') |