diff options
author | Jordan Borean <jborean93@gmail.com> | 2024-08-18 20:21:24 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-08-18 20:21:24 +0200 |
commit | 520fa688ba232ed165fc2dbd3b2be2ebde365ba1 (patch) | |
tree | 4679fb5e476849aa884f814bbbda871d521cdb90 /lib | |
parent | Add explicit winrm/psrp tests for HTTP and HTTPS (#83769) (diff) | |
download | ansible-520fa688ba232ed165fc2dbd3b2be2ebde365ba1.tar.xz ansible-520fa688ba232ed165fc2dbd3b2be2ebde365ba1.zip |
ssh and psrp - Support more complex characters in fetch_file (#83753)
* ssh and psrp - Support more complex chars in fetch_file
Fixes the psrp and ssh (with piped) fetch function to work with paths
that contains glob like characters in the path. For Windows this was
needed when using paths that contain `[]` in the path. For ssh this was
a problem with FreeBSD when using the piped transfer method with similar
characters.
Also tidies up the psrp logic to not inject the paths and buffer size
in the script but pass it as an object through an argument/parameter.
* Fix sanity check
Diffstat (limited to 'lib')
-rw-r--r-- | lib/ansible/plugins/connection/psrp.py | 39 | ||||
-rw-r--r-- | lib/ansible/plugins/connection/ssh.py | 2 |
2 files changed, 23 insertions, 18 deletions
diff --git a/lib/ansible/plugins/connection/psrp.py b/lib/ansible/plugins/connection/psrp.py index c9895d4450..abb9788ca1 100644 --- a/lib/ansible/plugins/connection/psrp.py +++ b/lib/ansible/plugins/connection/psrp.py @@ -632,39 +632,41 @@ end { buffer_size = max_b64_size - (max_b64_size % 1024) # setup the file stream with read only mode - setup_script = '''$ErrorActionPreference = "Stop" -$path = '%s' + setup_script = '''param([string]$Path) +$ErrorActionPreference = "Stop" -if (Test-Path -Path $path -PathType Leaf) { +if (Test-Path -LiteralPath $path -PathType Leaf) { $fs = New-Object -TypeName System.IO.FileStream -ArgumentList @( $path, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::Read ) - $buffer_size = %d } elseif (Test-Path -Path $path -PathType Container) { Write-Output -InputObject "[DIR]" } else { Write-Error -Message "$path does not exist" $host.SetShouldExit(1) -}''' % (self._shell._escape(in_path), buffer_size) +}''' # read the file stream at the offset and return the b64 string - read_script = '''$ErrorActionPreference = "Stop" -$fs.Seek(%d, [System.IO.SeekOrigin]::Begin) > $null -$buffer = New-Object -TypeName byte[] -ArgumentList $buffer_size -$bytes_read = $fs.Read($buffer, 0, $buffer_size) - -if ($bytes_read -gt 0) { - $bytes = $buffer[0..($bytes_read - 1)] - Write-Output -InputObject ([System.Convert]::ToBase64String($bytes)) + read_script = '''param([int64]$Offset, [int]$BufferSize) +$ErrorActionPreference = "Stop" +$fs.Seek($Offset, [System.IO.SeekOrigin]::Begin) > $null +$buffer = New-Object -TypeName byte[] -ArgumentList $BufferSize +$read = $fs.Read($buffer, 0, $buffer.Length) + +if ($read -gt 0) { + [System.Convert]::ToBase64String($buffer, 0, $read) }''' # need to run the setup script outside of the local scope so the # file stream stays active between fetch operations - rc, stdout, stderr = self._exec_psrp_script(setup_script, - use_local_scope=False) + rc, stdout, stderr = self._exec_psrp_script( + setup_script, + use_local_scope=False, + arguments=[in_path], + ) if rc != 0: raise AnsibleError("failed to setup file stream for fetch '%s': %s" % (out_path, to_native(stderr))) @@ -679,7 +681,10 @@ if ($bytes_read -gt 0) { while True: display.vvvvv("PSRP FETCH %s to %s (offset=%d" % (in_path, out_path, offset), host=self._psrp_host) - rc, stdout, stderr = self._exec_psrp_script(read_script % offset) + rc, stdout, stderr = self._exec_psrp_script( + read_script, + arguments=[offset, buffer_size], + ) if rc != 0: raise AnsibleError("failed to transfer file to '%s': %s" % (out_path, to_native(stderr))) @@ -813,7 +818,7 @@ if ($bytes_read -gt 0) { script: str, input_data: bytes | str | t.Iterable | None = None, use_local_scope: bool = True, - arguments: t.Iterable[str] | None = None, + arguments: t.Iterable[t.Any] | None = None, ) -> tuple[int, bytes, bytes]: # Check if there's a command on the current pipeline that still needs to be closed. if self._last_pipeline: diff --git a/lib/ansible/plugins/connection/ssh.py b/lib/ansible/plugins/connection/ssh.py index 5c4c28d525..4c58e0d947 100644 --- a/lib/ansible/plugins/connection/ssh.py +++ b/lib/ansible/plugins/connection/ssh.py @@ -1250,7 +1250,7 @@ class Connection(ConnectionBase): if sftp_action == 'get': # we pass sudoable=False to disable pty allocation, which # would end up mixing stdout/stderr and screwing with newlines - (returncode, stdout, stderr) = self.exec_command('dd if=%s bs=%s' % (in_path, BUFSIZE), sudoable=False) + (returncode, stdout, stderr) = self.exec_command('dd if=%s bs=%s' % (self._shell.quote(in_path), BUFSIZE), sudoable=False) with open(to_bytes(out_path, errors='surrogate_or_strict'), 'wb+') as out_file: out_file.write(stdout) else: |