I am implementing a rudimentary ssh client capable of securely sending a single command to an OpenSSH server. My client is currently able to handle everything up to sending service requests to the server (ie. I have derived keys from a Diffie-Hellman exchange). My goal is to send a single command (ie. whoami) to the server.
Once key exchange has been completed successfully, I am sending these packets in the following order in accordance with binary packet protocol. Each message has been unencrypted, and I've bolded the message IDs for each of the messages.
#1: Authentication service request
byte SSH_MSG_SERVICE_REQUEST
string “ssh-userauth”
Packet sent: 00 00 00 1c 0a 05 00 00 00 0c 73 73 68 2d 75 73 65 72 61 75 74 68 31 89 4b 1f 27 2f 02 98 f0 0d
Server response: 00 00 00 1c 0a 06 00 00 00 0c 73 73 68 2d 75 73 65 72 61 75 74 68 89 da 3a a3 b3 63 8e 8d c5 40
#2: Authentication information
byte SSH_MSG_USERAUTH_REQUEST
string user name
string “ssh-connection”
string "password"
boolean FALSE
string plaintext password
Packet sent: 00 00 00 3c 0b 32 00 00 00 04 XX XX XX XX 00 00 00 0e 73 73 68 2d 63 6f 6e 6e 65 63 74 69 6f 6e 00 00 00 08 70 61 73 73 77 6f 72 64 00 00 00 00 04 XX XX XX XX 31 89 4b 1f 27 2f 02 98 f0 0d 25
(omitted username and password)
Server’s response: 00 00 00 0c 0a 34 de f3 3b 8c 20 ca 6b 0f 69 43
This indicates that I am authenticating successfully and the server is ready for the client to open channels.
I are getting responses I expect up until this point, so I'm assuming server auth has been completed successfully, so I move on to opening a session channel:
Expected #4: Open session channel
byte SSH_MSG_CHANNEL_OPEN
string "session"
uint32 sender channel
uint32 initial window size
uint32 maximum packet size
Packet sent: 00 00 00 1c 03 5a 00 00 00 07 73 65 73 73 69 6f 6e 00 00 00 01 00 00 04 00 00 00 04 00 06 c4 3d
Server’s response: 00 00 00 1c 0a 5b 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 00 c6 ee 88 13 f7 78 ba a0 1d ea
The server responds with a 5b code (SSH_MSG_CHANNEL_OPEN_CONFIRMATION), so the channel open request seems to have been carried out correctly as well; however, I don't understand why the window size is set to 0 (may be relevant later).
I now want to request execution of a command: "whoami". So I send a message channel request:
Expected #5: Send command to server
byte SSH_MSG_CHANNEL_REQUEST
uint32 recipient channel
string "exec"
boolean want reply
string “whoami”
Packet sent: 00 00 00 2c 13 62 00 00 00 00 00 00 00 04 65 78 65 63 01 00 00 00 06 77 68 6f 61 6d 69 ad de 4d 6c dd b7 8e 19 3f 68 7a 8e 5a 63 10 99 2e dd 54
Here's where I get confused, packet received: 00 00 00 1c 12 5d 00 00 00 00 00 20 00 00 fd fa 83 ae 1d 50 ca 25 7c 42 6b 71 a7 ea dc 9f 9a 41 12 8d ff 45 f6 84 c0 36 a0 10 12 f8 01 c5 11 80 49 4c 95 9c be ec b2 b2 49 70 3e e3 d8 1e 3c 68 78 79 c5 b9
The server sends back a SSH_MSG_CHANNEL_WINDOW_ADJUST packet which is unexpected since I'm just requesting the results of "whoami," but I suspect it has to do with the fact that in the server's channel open confirmation message, the server sent that the window size is 0. Also, from reading RFC 4254 it doesn't seem like the server wants a response to this window adjust message.
What I'm even more confused about is how this packet seems to deviate from the binary packet protocol. The length is 1c, but the number of bytes the client is sent is much more than that, and the padding length is 12, but even after the 12 bytes of padding, there is more to the message.
Any insight into what this extra information is in the packet?
Am I missing a step in the connection or messing up a step?
The issue was that I didn't realize that the server was sending multiple messages within a single packet.
My client was correctly decrypting the first message, but not the second.
The server response looks something like this:
(encrypted packet 1 || MAC 1 || encrypted packet 2 || MAC 2 ...)
But I was expecting it to looks like this:
(encrypted packet 1 || MAC 1)