Skip to content

Commit 946c7c1

Browse files
authored
Merge pull request #271 from rustyscottweber/stdin_development
Add a function to send input to a running process.
2 parents fe59460 + ccc8cff commit 946c7c1

File tree

3 files changed

+237
-0
lines changed

3 files changed

+237
-0
lines changed

winrm/protocol.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,39 @@ def cleanup_command(self, shell_id, command_id):
395395
# TODO change assert into user-friendly exception
396396
assert uuid.UUID(relates_to.replace('uuid:', '')) == message_id
397397

398+
def send_command_input(self, shell_id, command_id, stdin_input, end=False):
399+
"""
400+
Send input to the given shell and command.
401+
@param string shell_id: The shell id on the remote machine.
402+
See #open_shell
403+
@param string command_id: The command id on the remote machine.
404+
See #run_command
405+
@param string stdin_input: The input unicode string or byte string to be sent.
406+
@param bool end: Boolean value which will close the stdin stream. If end=True then the stdin pipe to the
407+
remotely running process will be closed causing the next read by the remote process to stdin to return a
408+
EndOfFile error; the behavior of each process when this error is encountered is defined by the process, but most
409+
processes ( like CMD and powershell for instance) will just exit. Setting this value to 'True' means that no
410+
more input will be able to be sent to the process and attempting to do so should result in an error.
411+
@return: None
412+
"""
413+
if isinstance(stdin_input, text_type):
414+
stdin_input = stdin_input.encode("437")
415+
req = {'env:Envelope': self._get_soap_header(
416+
resource_uri='http://schemas.microsoft.com/wbem/wsman/1/windows/shell/cmd', # NOQA
417+
action='http://schemas.microsoft.com/wbem/wsman/1/windows/shell/Send', # NOQA
418+
shell_id=shell_id)}
419+
stdin_envelope = req['env:Envelope'].setdefault('env:Body', {}).setdefault(
420+
'rsp:Send', {}).setdefault('rsp:Stream', {})
421+
stdin_envelope['@CommandId'] = command_id
422+
stdin_envelope['@Name'] = 'stdin'
423+
if end:
424+
stdin_envelope['@End'] = "true"
425+
else:
426+
stdin_envelope['@End'] = "false"
427+
stdin_envelope['@xmlns:rsp'] = 'http://schemas.microsoft.com/wbem/wsman/1/windows/shell'
428+
stdin_envelope['#text'] = base64.b64encode(stdin_input)
429+
self.send_message(xmltodict.unparse(req))
430+
398431
def get_command_output(self, shell_id, command_id):
399432
"""
400433
Get the Output of the given shell and command

winrm/tests/conftest.py

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,188 @@
311311
</s:Envelope>"""
312312

313313

314+
run_cmd_req_input = """\
315+
<?xml version="1.0" encoding="utf-8"?>
316+
<env:Envelope xmlns:x="http://schemas.xmlsoap.org/ws/2004/09/transfer" xmlns:w="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd" xmlns:cfg="http://schemas.microsoft.com/wbem/wsman/1/config" xmlns:p="http://schemas.microsoft.com/wbem/wsman/1/wsman.xsd" xmlns:n="http://schemas.xmlsoap.org/ws/2004/09/enumeration" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:rsp="http://schemas.microsoft.com/wbem/wsman/1/windows/shell" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:b="http://schemas.dmtf.org/wbem/wsman/1/cimbinding.xsd" xmlns:a="http://schemas.xmlsoap.org/ws/2004/08/addressing">
317+
<env:Header>
318+
<a:To>http://windows-host:5985/wsman</a:To>
319+
<a:ReplyTo>
320+
<a:Address mustUnderstand="true">http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address>
321+
</a:ReplyTo>
322+
<w:MaxEnvelopeSize mustUnderstand="true">153600</w:MaxEnvelopeSize>
323+
<a:MessageID>uuid:11111111-1111-1111-1111-111111111111</a:MessageID>
324+
<w:Locale mustUnderstand="false" xml:lang="en-US" />
325+
<p:DataLocale mustUnderstand="false" xml:lang="en-US" />
326+
<w:OperationTimeout>PT20S</w:OperationTimeout>
327+
<w:ResourceURI mustUnderstand="true">http://schemas.microsoft.com/wbem/wsman/1/windows/shell/cmd</w:ResourceURI>
328+
<a:Action mustUnderstand="true">http://schemas.microsoft.com/wbem/wsman/1/windows/shell/Command</a:Action>
329+
<w:SelectorSet>
330+
<w:Selector Name="ShellId">11111111-1111-1111-1111-111111111113</w:Selector>
331+
</w:SelectorSet>
332+
<w:OptionSet>
333+
<w:Option Name="WINRS_CONSOLEMODE_STDIN">TRUE</w:Option>
334+
<w:Option Name="WINRS_SKIP_CMD_SHELL">FALSE</w:Option>
335+
</w:OptionSet>
336+
</env:Header>
337+
<env:Body>
338+
<rsp:CommandLine>
339+
<rsp:Command>cmd</rsp:Command>
340+
</rsp:CommandLine>
341+
</env:Body>
342+
</env:Envelope>"""
343+
344+
345+
run_cmd_req_input_response = """\
346+
<?xml version="1.0"?>
347+
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:x="http://schemas.xmlsoap.org/ws/2004/09/transfer" xmlns:w="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd" xmlns:rsp="http://schemas.microsoft.com/wbem/wsman/1/windows/shell" xmlns:p="http://schemas.microsoft.com/wbem/wsman/1/wsman.xsd" xml:lang="en-US">
348+
<s:Header>
349+
<a:Action>http://schemas.microsoft.com/wbem/wsman/1/windows/shell/CommandResponse</a:Action>
350+
<a:MessageID>uuid:11111111-1111-1111-1111-111111111114</a:MessageID>
351+
<a:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:To>
352+
<a:RelatesTo>uuid:11111111-1111-1111-1111-111111111112</a:RelatesTo>
353+
</s:Header>
354+
<s:Body>
355+
<rsp:CommandResponse>
356+
<rsp:CommandId>11111111-1111-1111-1111-111111111111</rsp:CommandId>
357+
</rsp:CommandResponse>
358+
</s:Body>
359+
</s:Envelope>
360+
"""
361+
362+
run_cmd_send_input = """\
363+
<?xml version="1.0" encoding="utf-8"?>
364+
<env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:b="http://schemas.dmtf.org/wbem/wsman/1/cimbinding.xsd" xmlns:n="http://schemas.xmlsoap.org/ws/2004/09/enumeration" xmlns:x="http://schemas.xmlsoap.org/ws/2004/09/transfer" xmlns:w="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd" xmlns:p="http://schemas.microsoft.com/wbem/wsman/1/wsman.xsd" xmlns:rsp="http://schemas.microsoft.com/wbem/wsman/1/windows/shell" xmlns:cfg="http://schemas.microsoft.com/wbem/wsman/1/config">
365+
<env:Header>
366+
<a:To>http://windows-host:5985/wsman</a:To>
367+
<a:ReplyTo>
368+
<a:Address mustUnderstand="true">http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address>
369+
</a:ReplyTo>
370+
<w:MaxEnvelopeSize mustUnderstand="true">153600</w:MaxEnvelopeSize>
371+
<a:MessageID>uuid:11111111-1111-1111-1111-111111111111</a:MessageID>
372+
<w:Locale mustUnderstand="false" xml:lang="en-US"/>
373+
<p:DataLocale mustUnderstand="false" xml:lang="en-US"/>
374+
<w:OperationTimeout>PT20S</w:OperationTimeout>
375+
<w:ResourceURI mustUnderstand="true">http://schemas.microsoft.com/wbem/wsman/1/windows/shell/cmd</w:ResourceURI>
376+
<a:Action mustUnderstand="true">http://schemas.microsoft.com/wbem/wsman/1/windows/shell/Send</a:Action>
377+
<w:SelectorSet>
378+
<w:Selector Name="ShellId">11111111-1111-1111-1111-111111111113</w:Selector>
379+
</w:SelectorSet>
380+
</env:Header>
381+
<env:Body>
382+
<rsp:Send>
383+
<rsp:Stream xmlns:rsp="http://schemas.microsoft.com/wbem/wsman/1/windows/shell" CommandId="11111111-1111-1111-1111-111111111111" Name="stdin" End="false" >ZWNobyAiaGVsbG8gd29ybGQiICYmIGV4aXQNCg==</rsp:Stream>
384+
</rsp:Send>
385+
</env:Body>
386+
</env:Envelope>
387+
"""
388+
389+
run_cmd_send_input_response = """\
390+
<?xml version="1.0" ?>
391+
<s:Envelope xml:lang="en-US" xmlns:a="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:p="http://schemas.microsoft.com/wbem/wsman/1/wsman.xsd" xmlns:rsp="http://schemas.microsoft.com/wbem/wsman/1/windows/shell" xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:w="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd" xmlns:x="http://schemas.xmlsoap.org/ws/2004/09/transfer">
392+
<s:Header>
393+
<a:Action>http://schemas.microsoft.com/wbem/wsman/1/windows/shell/SendResponse</a:Action>
394+
<a:MessageID>uuid:72371E37-E073-474B-B4BA-6559D8D94632</a:MessageID>
395+
<a:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:To>
396+
<a:RelatesTo>uuid:9c3de121-c3a4-452b-8f82-36b84e25b7fe</a:RelatesTo>
397+
</s:Header>
398+
<s:Body>
399+
<rsp:SendResponse/>
400+
</s:Body>
401+
</s:Envelope>
402+
"""
403+
404+
run_cmd_send_input_get_output = """\
405+
<?xml version="1.0" encoding="utf-8"?>
406+
<env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:b="http://schemas.dmtf.org/wbem/wsman/1/cimbinding.xsd" xmlns:n="http://schemas.xmlsoap.org/ws/2004/09/enumeration" xmlns:x="http://schemas.xmlsoap.org/ws/2004/09/transfer" xmlns:w="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd" xmlns:p="http://schemas.microsoft.com/wbem/wsman/1/wsman.xsd" xmlns:rsp="http://schemas.microsoft.com/wbem/wsman/1/windows/shell" xmlns:cfg="http://schemas.microsoft.com/wbem/wsman/1/config">
407+
<env:Header>
408+
<a:To>http://windows-host:5985/wsman</a:To>
409+
<a:ReplyTo>
410+
<a:Address mustUnderstand="true">http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address>
411+
</a:ReplyTo>
412+
<w:MaxEnvelopeSize mustUnderstand="true">153600</w:MaxEnvelopeSize>
413+
<a:MessageID>uuid:11111111-1111-1111-1111-111111111111</a:MessageID>
414+
<w:Locale mustUnderstand="false" xml:lang="en-US"/>
415+
<p:DataLocale mustUnderstand="false" xml:lang="en-US"/>
416+
<w:OperationTimeout>PT20S</w:OperationTimeout>
417+
<w:ResourceURI mustUnderstand="true">http://schemas.microsoft.com/wbem/wsman/1/windows/shell/cmd</w:ResourceURI>
418+
<a:Action mustUnderstand="true">http://schemas.microsoft.com/wbem/wsman/1/windows/shell/Receive</a:Action>
419+
<w:SelectorSet>
420+
<w:Selector Name="ShellId">11111111-1111-1111-1111-111111111113</w:Selector>
421+
</w:SelectorSet>
422+
</env:Header>
423+
<env:Body>
424+
<rsp:Receive>
425+
<rsp:DesiredStream CommandId="11111111-1111-1111-1111-111111111111">stdout stderr</rsp:DesiredStream>
426+
</rsp:Receive>
427+
</env:Body>
428+
</env:Envelope>
429+
"""
430+
431+
run_cmd_send_input_get_output_response = """\
432+
<?xml version="1.0"?>
433+
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:w="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd" xmlns:rsp="http://schemas.microsoft.com/wbem/wsman/1/windows/shell" xmlns:p="http://schemas.microsoft.com/wbem/wsman/1/wsman.xsd" xml:lang="en-US">
434+
<s:Header>
435+
<a:Action>http://schemas.microsoft.com/wbem/wsman/1/windows/shell/ReceiveResponse</a:Action>
436+
<a:MessageID>uuid:6468086A-377E-4BE3-AC71-1155F0F1D4E1</a:MessageID>
437+
<a:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:To>
438+
<a:RelatesTo>uuid:02f258b6-186f-4ac0-adc3-51550a131e64</a:RelatesTo>
439+
</s:Header>
440+
<s:Body>
441+
<rsp:ReceiveResponse>
442+
<rsp:Stream Name="stdout" CommandId="11111111-1111-1111-1111-111111111111">TWljcm9zb2Z0IFdpbmRvd3MgW1ZlcnNpb24gMTAuMC4xNzc2My4xMDdd</rsp:Stream>
443+
<rsp:Stream Name="stdout" CommandId="11111111-1111-1111-1111-111111111111">DQooYykgMjAxOCBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQoNCkM6XFVzZXJzXHJ3ZWJlcj5lY2hvIGhlbGxvIHdvcmxkICYmIGV4aXQNCmhlbGxvIHdvcmxkIA0K</rsp:Stream>
444+
<rsp:Stream Name="stdout" CommandId="11111111-1111-1111-1111-111111111111" End="true"/>
445+
<rsp:Stream Name="stderr" CommandId="11111111-1111-1111-1111-111111111111" End="true"/>
446+
<rsp:CommandState CommandId="11111111-1111-1111-1111-111111111111" State="http://schemas.microsoft.com/wbem/wsman/1/windows/shell/CommandState/Done">
447+
<rsp:ExitCode>0</rsp:ExitCode>
448+
</rsp:CommandState>
449+
</rsp:ReceiveResponse>
450+
</s:Body>
451+
</s:Envelope>
452+
"""
453+
454+
stdin_cmd_cleanup = """\
455+
<?xml version="1.0" encoding="utf-8"?>
456+
<env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:b="http://schemas.dmtf.org/wbem/wsman/1/cimbinding.xsd" xmlns:n="http://schemas.xmlsoap.org/ws/2004/09/enumeration" xmlns:x="http://schemas.xmlsoap.org/ws/2004/09/transfer" xmlns:w="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd" xmlns:p="http://schemas.microsoft.com/wbem/wsman/1/wsman.xsd" xmlns:rsp="http://schemas.microsoft.com/wbem/wsman/1/windows/shell" xmlns:cfg="http://schemas.microsoft.com/wbem/wsman/1/config">
457+
<env:Header>
458+
<a:To>http://windows-host:5985/wsman</a:To>
459+
<a:ReplyTo>
460+
<a:Address mustUnderstand="true">http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address>
461+
</a:ReplyTo>
462+
<w:MaxEnvelopeSize mustUnderstand="true">153600</w:MaxEnvelopeSize>
463+
<a:MessageID>uuid:11111111-1111-1111-1111-111111111111</a:MessageID>
464+
<w:Locale mustUnderstand="false" xml:lang="en-US"/>
465+
<p:DataLocale mustUnderstand="false" xml:lang="en-US"/>
466+
<w:OperationTimeout>PT20S</w:OperationTimeout>
467+
<w:ResourceURI mustUnderstand="true">http://schemas.microsoft.com/wbem/wsman/1/windows/shell/cmd</w:ResourceURI>
468+
<a:Action mustUnderstand="true">http://schemas.microsoft.com/wbem/wsman/1/windows/shell/Signal</a:Action>
469+
<w:SelectorSet>
470+
<w:Selector Name="ShellId">11111111-1111-1111-1111-111111111113</w:Selector>
471+
</w:SelectorSet>
472+
</env:Header>
473+
<env:Body>
474+
<rsp:Signal CommandId="11111111-1111-1111-1111-111111111111">
475+
<rsp:Code>http://schemas.microsoft.com/wbem/wsman/1/windows/shell/signal/terminate</rsp:Code>
476+
</rsp:Signal>
477+
</env:Body>
478+
</env:Envelope>
479+
"""
480+
481+
stdin_cmd_cleanup_response = """\
482+
<?xml version="1.0"?>
483+
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:x="http://schemas.xmlsoap.org/ws/2004/09/transfer" xmlns:w="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd" xmlns:rsp="http://schemas.microsoft.com/wbem/wsman/1/windows/shell" xmlns:p="http://schemas.microsoft.com/wbem/wsman/1/wsman.xsd" xml:lang="en-US">
484+
<s:Header>
485+
<a:Action>http://schemas.microsoft.com/wbem/wsman/1/windows/shell/SignalResponse</a:Action>
486+
<a:MessageID>uuid:8A875405-3494-4400-A988-B47A563922E7</a:MessageID>
487+
<a:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:To>
488+
<a:RelatesTo>uuid:11111111-1111-1111-1111-111111111111</a:RelatesTo>
489+
</s:Header>
490+
<s:Body>
491+
<rsp:SignalResponse/>
492+
</s:Body>
493+
</s:Envelope>
494+
"""
495+
314496
def sort_dict(ordered_dict):
315497
items = sorted(ordered_dict.items(), key=lambda x: x[0])
316498
ordered_dict.clear()
@@ -348,6 +530,14 @@ def send_message(self, message):
348530
return get_cmd_output_response
349531
elif xml_str_compare(message, get_cmd_ps_output_request % '2'):
350532
return get_ps_output_response
533+
elif xml_str_compare(message, run_cmd_req_input):
534+
return run_cmd_req_input_response
535+
elif xml_str_compare(message, run_cmd_send_input):
536+
return run_cmd_send_input_response
537+
elif xml_str_compare(message, run_cmd_send_input_get_output):
538+
return run_cmd_send_input_get_output_response
539+
elif xml_str_compare(message, stdin_cmd_cleanup):
540+
return stdin_cmd_cleanup_response
351541
else:
352542
raise Exception('Message was not expected\n\n%s' % message)
353543

winrm/tests/test_protocol.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,20 @@ def test_get_command_output(protocol_fake):
4141
protocol_fake.close_shell(shell_id)
4242

4343

44+
def test_send_command_input(protocol_fake):
45+
shell_id = protocol_fake.open_shell()
46+
command_id = protocol_fake.run_command(shell_id, u'cmd')
47+
protocol_fake.send_command_input(shell_id, command_id, u'echo "hello world" && exit\r\n')
48+
std_out, std_err, status_code = protocol_fake.get_command_output(
49+
shell_id, command_id)
50+
assert status_code == 0
51+
assert b'hello world' in std_out
52+
assert len(std_err) == 0
53+
54+
protocol_fake.cleanup_command(shell_id, command_id)
55+
protocol_fake.close_shell(shell_id)
56+
57+
4458
def test_set_timeout_as_sec():
4559
protocol = Protocol('endpoint',
4660
username='username',

0 commit comments

Comments
 (0)