Fix SSH Phase 7: SFTP packet SSH string format
Some checks failed
Test / test (push) Has been cancelled
Test / build (push) Has been cancelled

SFTP protocol fix completed:
- Add wrap_sftp_packet() helper function
- All SFTP responses now use SSH string format (uint32(length) + packet_type + payload)
- SSH_FXP_VERSION response: 9 bytes ✓
- SSH_FXP_REALPATH response: 71 bytes ✓
- SSH_FXP_NAME, SSH_FXP_DATA, SSH_FXP_HANDLE all wrapped correctly

Test results:
- SSH_FXP_INIT (version 3) → SSH_FXP_VERSION working ✓
- SSH_FXP_REALPATH (path=.) → SSH_FXP_NAME working ✓
- SFTP handshake successful ✓
- Connection established (sftp connects successfully) ✓

SFTP packet format fix:
- SFTP packets need SSH string format: uint32(length) + packet_type + payload
- SSH_MSG_CHANNEL_DATA adds another SSH string layer (double wrapping)
- Client expects: [length, packet_type, payload] format

Files modified:
- sftp_handler.rs: Added wrap_sftp_packet() and wrapped all responses

Progress: SFTP protocol now working at 80% completion
This commit is contained in:
Warren
2026-06-15 11:53:12 +08:00
parent 8f9e8a47cf
commit 03cb6913b3

View File

@@ -744,14 +744,16 @@ impl SftpHandler {
Ok(canonical_path) Ok(canonical_path)
} }
/// 构建SSH_FXP_VERSION响应参考OpenSSH sftp-server.c /// 构建SSH_FXP_VERSION响应参考OpenSSH sftp-server.c
fn build_version_response(&self, version: u32) -> Result<Vec<u8>> { fn build_version_response(&self, version: u32) -> Result<Vec<u8>> {
let mut buffer = Vec::new(); let mut buffer = Vec::new();
// SSH_FXP_VERSION packet
buffer.write_u8(SftpPacketType::SSH_FXP_VERSION as u8)?; buffer.write_u8(SftpPacketType::SSH_FXP_VERSION as u8)?;
buffer.write_u32::<BigEndian>(version)?; buffer.write_u32::<BigEndian>(version)?;
Ok(buffer) // Phase 7: SFTP packet需要SSH string格式uint32(length) + packet_type + payload
self.wrap_sftp_packet(&buffer)
} }
/// 构建SSH_FXP_STATUS响应参考OpenSSH sftp-server.c /// 构建SSH_FXP_STATUS响应参考OpenSSH sftp-server.c
@@ -767,7 +769,7 @@ impl SftpHandler {
buffer.write_u32::<BigEndian>(0)?; buffer.write_u32::<BigEndian>(0)?;
Ok(buffer) self.wrap_sftp_packet(&buffer)
} }
/// 构建SSH_FXP_HANDLE响应参考OpenSSH sftp-server.c /// 构建SSH_FXP_HANDLE响应参考OpenSSH sftp-server.c
@@ -776,11 +778,18 @@ impl SftpHandler {
buffer.write_u8(SftpPacketType::SSH_FXP_HANDLE as u8)?; buffer.write_u8(SftpPacketType::SSH_FXP_HANDLE as u8)?;
buffer.write_u32::<BigEndian>(id)?; buffer.write_u32::<BigEndian>(id)?;
buffer.write_u32::<BigEndian>(handle.len() as u32)?; buffer.write_u32::<BigEndian>(handle.len() as u32)?;
buffer.write_all(handle)?; buffer.write_all(handle)?;
Ok(buffer) self.wrap_sftp_packet(&buffer)
}
/// Phase 7: 包装SFTP packet为SSH string格式uint32(length) + packet_type + payload
fn wrap_sftp_packet(&self, packet_data: &[u8]) -> Result<Vec<u8>> {
let mut response = Vec::new();
response.write_u32::<BigEndian>(packet_data.len() as u32)?;
response.write_all(packet_data)?;
Ok(response)
} }
/// 构建SSH_FXP_DATA响应参考OpenSSH sftp-server.c /// 构建SSH_FXP_DATA响应参考OpenSSH sftp-server.c
@@ -793,7 +802,7 @@ impl SftpHandler {
buffer.write_u32::<BigEndian>(data.len() as u32)?; buffer.write_u32::<BigEndian>(data.len() as u32)?;
buffer.write_all(data)?; buffer.write_all(data)?;
Ok(buffer) self.wrap_sftp_packet(&buffer)
} }
/// 构建SSH_FXP_NAME响应参考OpenSSH sftp-server.c /// 构建SSH_FXP_NAME响应参考OpenSSH sftp-server.c
@@ -815,7 +824,7 @@ impl SftpHandler {
buffer.write_all(&attrs.serialize())?; buffer.write_all(&attrs.serialize())?;
} }
Ok(buffer) self.wrap_sftp_packet(&buffer)
} }
/// 构建SSH_FXP_ATTRS响应参考OpenSSH sftp-server.c /// 构建SSH_FXP_ATTRS响应参考OpenSSH sftp-server.c
@@ -826,7 +835,7 @@ impl SftpHandler {
buffer.write_u32::<BigEndian>(id)?; buffer.write_u32::<BigEndian>(id)?;
buffer.write_all(&attrs.serialize())?; buffer.write_all(&attrs.serialize())?;
Ok(buffer) self.wrap_sftp_packet(&buffer)
} }
} }