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,16 +744,18 @@ impl SftpHandler {
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>> {
let mut buffer = Vec::new();
// SSH_FXP_VERSION packet
buffer.write_u8(SftpPacketType::SSH_FXP_VERSION as u8)?;
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
fn build_status_response(&self, id: u32, status: SftpStatus, message: &str) -> Result<Vec<u8>> {
let mut buffer = Vec::new();
@@ -767,22 +769,29 @@ impl SftpHandler {
buffer.write_u32::<BigEndian>(0)?;
Ok(buffer)
self.wrap_sftp_packet(&buffer)
}
/// 构建SSH_FXP_HANDLE响应参考OpenSSH sftp-server.c
fn build_handle_response(&self, id: u32, handle: &[u8]) -> Result<Vec<u8>> {
let mut buffer = Vec::new();
buffer.write_u8(SftpPacketType::SSH_FXP_HANDLE as u8)?;
buffer.write_u32::<BigEndian>(id)?;
buffer.write_u32::<BigEndian>(handle.len() as u32)?;
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
fn build_data_response(&self, id: u32, data: &[u8]) -> Result<Vec<u8>> {
let mut buffer = Vec::new();
@@ -793,9 +802,9 @@ impl SftpHandler {
buffer.write_u32::<BigEndian>(data.len() as u32)?;
buffer.write_all(data)?;
Ok(buffer)
self.wrap_sftp_packet(&buffer)
}
/// 构建SSH_FXP_NAME响应参考OpenSSH sftp-server.c
fn build_name_response(&self, id: u32, entries: Vec<(String, SftpAttrs)>) -> Result<Vec<u8>> {
let mut buffer = Vec::new();
@@ -815,9 +824,9 @@ impl SftpHandler {
buffer.write_all(&attrs.serialize())?;
}
Ok(buffer)
self.wrap_sftp_packet(&buffer)
}
/// 构建SSH_FXP_ATTRS响应参考OpenSSH sftp-server.c
fn build_attrs_response(&self, id: u32, attrs: &SftpAttrs) -> Result<Vec<u8>> {
let mut buffer = Vec::new();
@@ -826,7 +835,7 @@ impl SftpHandler {
buffer.write_u32::<BigEndian>(id)?;
buffer.write_all(&attrs.serialize())?;
Ok(buffer)
self.wrap_sftp_packet(&buffer)
}
}